Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Only check examples, not arbitrary subpackages
  • Loading branch information
stuartmorgan-g committed May 17, 2022
commit 2081d0feaab0cd3c6a7965b9abc05db72aea9b57
43 changes: 37 additions & 6 deletions script/tool/lib/src/common/package_looping_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ import 'plugin_command.dart';
import 'process_runner.dart';
import 'repository_package.dart';

/// Enumeration options for package looping commands.
enum PackageLoopingType {
/// Only enumerates the top level packages, without including any of their
/// subpackages.
topLevelOnly,

/// Enumerates the top level packages and any example packages they contain.
includeExamples,

/// Enumerates all packages recursively, including both example and
/// non-example subpackages.
includeAllSubpackages,
}

/// Possible outcomes of a command run for a package.
enum RunState {
/// The command succeeded for the package.
Expand Down Expand Up @@ -109,9 +123,26 @@ abstract class PackageLoopingCommand extends PluginCommand {
/// Note: Consistent behavior across commands whenever possibel is a goal for
/// this tool, so this should be overridden only in rare cases.
Stream<PackageEnumerationEntry> getPackagesToProcess() async* {
yield* includeSubpackages
? getTargetPackagesAndSubpackages(filterExcluded: false)
: getTargetPackages(filterExcluded: false);
switch (packageLoopingType) {
case PackageLoopingType.topLevelOnly:
yield* getTargetPackages(filterExcluded: false);
break;
case PackageLoopingType.includeExamples:
await for (final PackageEnumerationEntry packageEntry
in getTargetPackages(filterExcluded: false)) {
yield packageEntry;
yield* Stream<PackageEnumerationEntry>.fromIterable(packageEntry
.package
.getExamples()
.map((RepositoryPackage package) => PackageEnumerationEntry(
package,
excluded: packageEntry.excluded)));
}
break;
case PackageLoopingType.includeAllSubpackages:
yield* getTargetPackagesAndSubpackages(filterExcluded: false);
break;
}
}

/// Runs the command for [package], returning a list of errors.
Expand Down Expand Up @@ -140,9 +171,9 @@ abstract class PackageLoopingCommand extends PluginCommand {
/// to make the output structure easier to follow.
bool get hasLongOutput => true;

/// Whether to loop over all packages (e.g., including example/), rather than
/// only top-level packages.
bool get includeSubpackages => false;
/// Whether to loop over top-level packages only, or some or all of their
/// sub-packages as well.
PackageLoopingType get packageLoopingType => PackageLoopingType.topLevelOnly;

/// The text to output at the start when reporting one or more failures.
/// This will be followed by a list of packages that reported errors, with
Expand Down
1 change: 1 addition & 0 deletions script/tool/lib/src/common/repository_package.dart
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class RepositoryPackage {
!isPlatformInterface &&
directory.basename != directory.parent.basename;

/// True if the package is an example for another package.
bool get isExample =>
(directory.basename == 'example' && isPackage(directory.parent)) ||
(directory.parent.basename == 'example' &&
Expand Down
3 changes: 2 additions & 1 deletion script/tool/lib/src/pubspec_check_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class PubspecCheckCommand extends PackageLoopingCommand {
bool get hasLongOutput => false;

@override
bool get includeSubpackages => true;
PackageLoopingType get packageLoopingType =>
PackageLoopingType.includeAllSubpackages;

@override
Future<PackageResult> runForPackage(RepositoryPackage package) async {
Expand Down
3 changes: 2 additions & 1 deletion script/tool/lib/src/readme_check_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ class ReadmeCheckCommand extends PackageLoopingCommand {
bool get hasLongOutput => false;

@override
bool get includeSubpackages => true;
PackageLoopingType get packageLoopingType =>
PackageLoopingType.includeExamples;

@override
Future<PackageResult> runForPackage(RepositoryPackage package) async {
Expand Down
3 changes: 2 additions & 1 deletion script/tool/lib/src/test_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class TestCommand extends PackageLoopingCommand {
'This command requires "flutter" to be in your path.';

@override
bool get includeSubpackages => true;
PackageLoopingType get packageLoopingType =>
PackageLoopingType.includeAllSubpackages;

@override
Future<PackageResult> runForPackage(RepositoryPackage package) async {
Expand Down
80 changes: 69 additions & 11 deletions script/tool/test/common/package_looping_command_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ void main() {
TestPackageLoopingCommand createTestCommand({
String gitDiffResponse = '',
bool hasLongOutput = true,
bool includeSubpackages = false,
PackageLoopingType packageLoopingType = PackageLoopingType.topLevelOnly,
bool failsDuringInit = false,
bool warnsDuringInit = false,
bool warnsDuringCleanup = false,
Expand All @@ -122,7 +122,7 @@ void main() {
packagesDir,
platform: mockPlatform,
hasLongOutput: hasLongOutput,
includeSubpackages: includeSubpackages,
packageLoopingType: packageLoopingType,
failsDuringInit: failsDuringInit,
warnsDuringInit: warnsDuringInit,
warnsDuringCleanup: warnsDuringCleanup,
Expand Down Expand Up @@ -236,14 +236,17 @@ void main() {
unorderedEquals(<String>[package1.path, package2.path]));
});

test('includes subpackages when requested', () async {
test('includes all subpackages when requested', () async {
final RepositoryPackage plugin = createFakePlugin('a_plugin', packagesDir,
examples: <String>['example1', 'example2']);
final RepositoryPackage package =
createFakePackage('a_package', packagesDir);
final RepositoryPackage subPackage = createFakePackage(
'sub_package', package.directory,
examples: <String>[]);

final TestPackageLoopingCommand command =
createTestCommand(includeSubpackages: true);
final TestPackageLoopingCommand command = createTestCommand(
packageLoopingType: PackageLoopingType.includeAllSubpackages);
await runCommand(command);

expect(
Expand All @@ -254,18 +257,72 @@ void main() {
getExampleDir(plugin).childDirectory('example2').path,
package.path,
getExampleDir(package).path,
subPackage.path,
]));
});

test('includes examples when requested', () async {
final RepositoryPackage plugin = createFakePlugin('a_plugin', packagesDir,
examples: <String>['example1', 'example2']);
final RepositoryPackage package =
createFakePackage('a_package', packagesDir);
final RepositoryPackage subPackage =
createFakePackage('sub_package', package.directory);

final TestPackageLoopingCommand command = createTestCommand(
packageLoopingType: PackageLoopingType.includeExamples);
await runCommand(command);

expect(
command.checkedPackages,
unorderedEquals(<String>[
plugin.path,
getExampleDir(plugin).childDirectory('example1').path,
getExampleDir(plugin).childDirectory('example2').path,
package.path,
getExampleDir(package).path,
]));
expect(command.checkedPackages, isNot(contains(subPackage.path)));
});

test('excludes subpackages when main package is excluded', () async {
final RepositoryPackage excluded = createFakePlugin(
'a_plugin', packagesDir,
examples: <String>['example1', 'example2']);
final RepositoryPackage included =
createFakePackage('a_package', packagesDir);
final RepositoryPackage subpackage =
createFakePackage('sub_package', excluded.directory);

final TestPackageLoopingCommand command =
createTestCommand(includeSubpackages: true);
final TestPackageLoopingCommand command = createTestCommand(
packageLoopingType: PackageLoopingType.includeAllSubpackages);
await runCommand(command, arguments: <String>['--exclude=a_plugin']);

final Iterable<RepositoryPackage> examples = excluded.getExamples();

expect(
command.checkedPackages,
unorderedEquals(<String>[
included.path,
getExampleDir(included).path,
]));
expect(command.checkedPackages, isNot(contains(excluded.path)));
expect(examples.length, 2);
for (final RepositoryPackage example in examples) {
expect(command.checkedPackages, isNot(contains(example.path)));
}
expect(command.checkedPackages, isNot(contains(subpackage.path)));
});

test('excludes examples when main package is excluded', () async {
final RepositoryPackage excluded = createFakePlugin(
'a_plugin', packagesDir,
examples: <String>['example1', 'example2']);
final RepositoryPackage included =
createFakePackage('a_package', packagesDir);

final TestPackageLoopingCommand command = createTestCommand(
packageLoopingType: PackageLoopingType.includeExamples);
await runCommand(command, arguments: <String>['--exclude=a_plugin']);

final Iterable<RepositoryPackage> examples = excluded.getExamples();
Expand All @@ -290,8 +347,9 @@ void main() {
final RepositoryPackage included =
createFakePackage('a_package', packagesDir);

final TestPackageLoopingCommand command =
createTestCommand(includeSubpackages: true, hasLongOutput: false);
final TestPackageLoopingCommand command = createTestCommand(
packageLoopingType: PackageLoopingType.includeAllSubpackages,
hasLongOutput: false);
final List<String> output = await runCommand(command, arguments: <String>[
'--skip-if-not-supporting-flutter-version=2.5.0'
]);
Expand Down Expand Up @@ -769,7 +827,7 @@ class TestPackageLoopingCommand extends PackageLoopingCommand {
Directory packagesDir, {
required Platform platform,
this.hasLongOutput = true,
this.includeSubpackages = false,
this.packageLoopingType = PackageLoopingType.topLevelOnly,
this.customFailureListHeader,
this.customFailureListFooter,
this.failsDuringInit = false,
Expand All @@ -795,7 +853,7 @@ class TestPackageLoopingCommand extends PackageLoopingCommand {
bool hasLongOutput;

@override
bool includeSubpackages;
PackageLoopingType packageLoopingType;

@override
String get failureListHeader =>
Expand Down
23 changes: 17 additions & 6 deletions script/tool/test/readme_check_command_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ void main() {
});

test('skips when example README is missing', () async {
final RepositoryPackage package =
createFakePackage('a_package', packagesDir);
createFakePackage('a_package', packagesDir);

final List<String> output =
await runCapturingPrint(runner, <String>['readme-check']);
Expand All @@ -72,6 +71,20 @@ void main() {
);
});

test('does not inculde non-example subpackages', () async {
final RepositoryPackage package =
createFakePackage('a_package', packagesDir);
const String subpackageName = 'special_test';
final RepositoryPackage miscSubpackage =
createFakePackage(subpackageName, package.directory);
miscSubpackage.readmeFile.delete();

final List<String> output =
await runCapturingPrint(runner, <String>['readme-check']);

expect(output, isNot(contains(subpackageName)));
});

test('fails when README still has plugin template boilerplate', () async {
final RepositoryPackage package = createFakePlugin('a_plugin', packagesDir);
package.readmeFile.writeAsStringSync('''
Expand Down Expand Up @@ -171,8 +184,7 @@ samples, guidance on mobile development, and a full API reference.

test('fails when non-federated plugin is missing an OS support table',
() async {
final RepositoryPackage plugin =
createFakePlugin('a_plugin', packagesDir);
createFakePlugin('a_plugin', packagesDir);

Error? commandError;
final List<String> output = await runCapturingPrint(
Expand All @@ -192,8 +204,7 @@ samples, guidance on mobile development, and a full API reference.
test(
'fails when app-facing part of a federated plugin is missing an OS support table',
() async {
final RepositoryPackage plugin =
createFakePlugin('a_plugin', packagesDir.childDirectory('a_plugin'));
createFakePlugin('a_plugin', packagesDir.childDirectory('a_plugin'));

Error? commandError;
final List<String> output = await runCapturingPrint(
Expand Down