Skip to content

Commit fa2e8a0

Browse files
[tool] Support code excerpts for any .md file (flutter#4212)
Updates `update-excerpts` to support any top-level .md file (other than CHANGELOG.md), rather than just README.md. This is useful for supplemental content, such as migration guides linked from the main README file. Also makes some small improvements to the error messaging: - The list of incorrect files is now relative to, and restricted to, the package. This makes the error message simpler, and ensures that changed files in other packages don't get listed. - Adds a link to the relevant wiki docs, since this has been a source of confusion for newer contributors.
1 parent c3faadd commit fa2e8a0

File tree

2 files changed

+80
-20
lines changed

2 files changed

+80
-20
lines changed

script/tool/lib/src/update_excerpts_command.dart

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import 'common/package_looping_command.dart';
1515
import 'common/process_runner.dart';
1616
import 'common/repository_package.dart';
1717

18-
/// A command to update README code excerpts from code files.
18+
/// A command to update .md code excerpts from code files.
1919
class UpdateExcerptsCommand extends PackageLoopingCommand {
2020
/// Creates a excerpt updater command instance.
2121
UpdateExcerptsCommand(
@@ -51,7 +51,7 @@ class UpdateExcerptsCommand extends PackageLoopingCommand {
5151
final String name = 'update-excerpts';
5252

5353
@override
54-
final String description = 'Updates code excerpts in README.md files, based '
54+
final String description = 'Updates code excerpts in .md files, based '
5555
'on code from code files, via code-excerpt';
5656

5757
@override
@@ -105,13 +105,16 @@ class UpdateExcerptsCommand extends PackageLoopingCommand {
105105
}
106106

107107
if (getBoolArg(_failOnChangeFlag)) {
108-
final String? stateError = await _validateRepositoryState();
108+
final String? stateError = await _validateRepositoryState(package);
109109
if (stateError != null) {
110-
printError('README.md is out of sync with its source excerpts.\n\n'
111-
'If you edited code in README.md directly, you should instead edit '
112-
'the example source files. If you edited source files, run the '
113-
'repository tooling\'s "$name" command on this package, and update '
114-
'your PR with the resulting changes.');
110+
printError('One or more .md files are out of sync with their source '
111+
'excerpts.\n\n'
112+
'If you edited code in a .md file directly, you should instead '
113+
'edit the example source files. If you edited source files, run '
114+
'the repository tooling\'s "$name" command on this package, and '
115+
'update your PR with the resulting changes.\n\n'
116+
'For more information, see '
117+
'https://github.com/flutter/flutter/wiki/Contributing-to-Plugins-and-Packages#readme-code');
115118
return PackageResult.fail(<String>[stateError]);
116119
}
117120
}
@@ -138,14 +141,24 @@ class UpdateExcerptsCommand extends PackageLoopingCommand {
138141
return exitCode == 0;
139142
}
140143

141-
/// Runs the injection step to update [targetPackage]'s README with the latest
142-
/// excerpts from [example], returning true on success.
144+
/// Runs the injection step to update [targetPackage]'s top-level .md files
145+
/// with the latest excerpts from [example], returning true on success.
143146
Future<bool> _injectSnippets(
144147
RepositoryPackage example, {
145148
required RepositoryPackage targetPackage,
146149
}) async {
147-
final String relativeReadmePath =
148-
getRelativePosixPath(targetPackage.readmeFile, from: example.directory);
150+
final List<String> relativeMdPaths = targetPackage.directory
151+
.listSync()
152+
.whereType<File>()
153+
.where((File f) =>
154+
f.basename.toLowerCase().endsWith('.md') &&
155+
// Exclude CHANGELOG since it should never have excerpts.
156+
f.basename != 'CHANGELOG.md')
157+
.map((File f) => getRelativePosixPath(f, from: example.directory))
158+
.toList();
159+
if (relativeMdPaths.isEmpty) {
160+
return true;
161+
}
149162
final int exitCode = await processRunner.runAndStream(
150163
'dart',
151164
<String>[
@@ -154,7 +167,7 @@ class UpdateExcerptsCommand extends PackageLoopingCommand {
154167
'--write-in-place',
155168
'--yaml',
156169
'--no-escape-ng-interpolation',
157-
relativeReadmePath,
170+
...relativeMdPaths,
158171
],
159172
workingDir: example.directory);
160173
return exitCode == 0;
@@ -212,11 +225,11 @@ class UpdateExcerptsCommand extends PackageLoopingCommand {
212225

213226
/// Checks the git state, returning an error string if any .md files have
214227
/// changed.
215-
Future<String?> _validateRepositoryState() async {
228+
Future<String?> _validateRepositoryState(RepositoryPackage package) async {
216229
final io.ProcessResult checkFiles = await processRunner.run(
217230
'git',
218231
<String>['ls-files', '--modified'],
219-
workingDir: packagesDir,
232+
workingDir: package.directory,
220233
logOnError: true,
221234
);
222235
if (checkFiles.exitCode != 0) {

script/tool/test/update_excerpts_command_test.dart

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ void main() {
111111

112112
test('updates example readme when config is present', () async {
113113
final RepositoryPackage package = createFakePlugin('a_package', packagesDir,
114-
extraFiles: <String>[kReadmeExcerptConfigPath]);
114+
extraFiles: <String>[kReadmeExcerptConfigPath, 'example/README.md']);
115115
final Directory example = getExampleDir(package);
116116

117117
final List<String> output =
@@ -153,6 +153,52 @@ void main() {
153153
]));
154154
});
155155

156+
test('includes all top-level .md files', () async {
157+
const String otherMdFileName = 'another_file.md';
158+
final RepositoryPackage package = createFakePlugin('a_package', packagesDir,
159+
extraFiles: <String>[kReadmeExcerptConfigPath, otherMdFileName]);
160+
final Directory example = getExampleDir(package);
161+
162+
final List<String> output =
163+
await runCapturingPrint(runner, <String>['update-excerpts']);
164+
165+
expect(
166+
processRunner.recordedCalls,
167+
containsAll(<ProcessCall>[
168+
ProcessCall(
169+
'dart',
170+
const <String>[
171+
'run',
172+
'build_runner',
173+
'build',
174+
'--config',
175+
'excerpt',
176+
'--output',
177+
'excerpts',
178+
'--delete-conflicting-outputs',
179+
],
180+
example.path),
181+
ProcessCall(
182+
'dart',
183+
const <String>[
184+
'run',
185+
'code_excerpt_updater',
186+
'--write-in-place',
187+
'--yaml',
188+
'--no-escape-ng-interpolation',
189+
'../README.md',
190+
'../$otherMdFileName',
191+
],
192+
example.path),
193+
]));
194+
195+
expect(
196+
output,
197+
containsAllInOrder(<Matcher>[
198+
contains('Ran for 1 package(s)'),
199+
]));
200+
});
201+
156202
test('skips when no config is present', () async {
157203
createFakePlugin('a_package', packagesDir);
158204

@@ -277,7 +323,7 @@ void main() {
277323

278324
test('fails if example injection fails', () async {
279325
createFakePlugin('a_package', packagesDir,
280-
extraFiles: <String>[kReadmeExcerptConfigPath]);
326+
extraFiles: <String>[kReadmeExcerptConfigPath, 'example/README.md']);
281327

282328
processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
283329
FakeProcessInfo(MockProcess(), <String>['pub', 'get']),
@@ -307,7 +353,7 @@ void main() {
307353
createFakePlugin('a_plugin', packagesDir,
308354
extraFiles: <String>[kReadmeExcerptConfigPath]);
309355

310-
const String changedFilePath = 'packages/a_plugin/README.md';
356+
const String changedFilePath = 'README.md';
311357
processRunner.mockProcessesForExecutable['git'] = <FakeProcessInfo>[
312358
FakeProcessInfo(MockProcess(stdout: changedFilePath)),
313359
];
@@ -323,9 +369,10 @@ void main() {
323369
expect(
324370
output,
325371
containsAllInOrder(<Matcher>[
326-
contains('README.md is out of sync with its source excerpts'),
372+
contains(
373+
'One or more .md files are out of sync with their source excerpts'),
327374
contains('Snippets are out of sync in the following files: '
328-
'packages/a_plugin/README.md'),
375+
'$changedFilePath'),
329376
]));
330377
});
331378

0 commit comments

Comments
 (0)