[tools] Convert test utils to RepositoryPackage (#5605)

This commit is contained in:
stuartmorgan
2022-05-03 17:14:11 -04:00
committed by GitHub
parent 5a06b47e51
commit 5ec6644f3f
39 changed files with 1124 additions and 986 deletions

View File

@ -30,14 +30,22 @@ const String platformWindows = 'windows';
/// Key for enable experiment.
const String kEnableExperiment = 'enable-experiment';
/// Target platforms supported by Flutter.
// ignore: public_member_api_docs
enum FlutterPlatform { android, ios, linux, macos, web, windows }
/// Returns whether the given directory is a Dart package.
bool isPackage(FileSystemEntity entity) {
if (entity is! Directory) {
return false;
}
// Per https://dart.dev/guides/libraries/create-library-packages#what-makes-a-library-package
return entity.childFile('pubspec.yaml').existsSync() &&
entity.childDirectory('lib').existsSync();
// According to
// https://dart.dev/guides/libraries/create-library-packages#what-makes-a-library-package
// a package must also have a `lib/` directory, but in practice that's not
// always true. flutter/plugins has some special cases (espresso, some
// federated implementation packages) that don't have any source, so this
// deliberately doesn't check that there's a lib directory.
return entity.childFile('pubspec.yaml').existsSync();
}
/// Prints `successMessage` in green.

View File

@ -6,6 +6,7 @@ import 'package:file/file.dart';
import 'package:platform/platform.dart';
import 'process_runner.dart';
import 'repository_package.dart';
const String _gradleWrapperWindows = 'gradlew.bat';
const String _gradleWrapperNonWindows = 'gradlew';
@ -21,7 +22,7 @@ class GradleProject {
});
/// The directory of a Flutter project to run Gradle commands in.
final Directory flutterProject;
final RepositoryPackage flutterProject;
/// The [ProcessRunner] used to run commands. Overridable for testing.
final ProcessRunner processRunner;
@ -30,7 +31,8 @@ class GradleProject {
final Platform platform;
/// The project's 'android' directory.
Directory get androidDirectory => flutterProject.childDirectory('android');
Directory get androidDirectory =>
flutterProject.platformDirectory(FlutterPlatform.android);
/// The path to the Gradle wrapper file for the project.
File get gradleWrapper => androidDirectory.childFile(

View File

@ -368,7 +368,7 @@ abstract class PluginCommand extends Command<void> {
await for (final FileSystemEntity entity
in dir.list(followLinks: false)) {
// A top-level Dart package is a plugin package.
if (_isDartPackage(entity)) {
if (isPackage(entity)) {
if (packages.isEmpty || packages.contains(p.basename(entity.path))) {
yield PackageEnumerationEntry(
RepositoryPackage(entity as Directory),
@ -378,7 +378,7 @@ abstract class PluginCommand extends Command<void> {
// Look for Dart packages under this top-level directory.
await for (final FileSystemEntity subdir
in entity.list(followLinks: false)) {
if (_isDartPackage(subdir)) {
if (isPackage(subdir)) {
// There are three ways for a federated plugin to match:
// - package name (path_provider_android)
// - fully specified name (path_provider/path_provider_android)
@ -427,9 +427,9 @@ abstract class PluginCommand extends Command<void> {
{bool filterExcluded = true}) async* {
yield* package.directory
.list(recursive: true, followLinks: false)
.where(_isDartPackage)
.where(isPackage)
.map((FileSystemEntity directory) =>
// _isDartPackage guarantees that this cast is valid.
// isPackage guarantees that this cast is valid.
RepositoryPackage(directory as Directory));
}
@ -448,12 +448,6 @@ abstract class PluginCommand extends Command<void> {
.cast<File>();
}
/// Returns whether the specified entity is a directory containing a
/// `pubspec.yaml` file.
bool _isDartPackage(FileSystemEntity entity) {
return entity is Directory && entity.childFile('pubspec.yaml').existsSync();
}
/// Retrieve an instance of [GitVersionFinder] based on `_baseShaArg` and [gitDir].
///
/// Throws tool exit if [gitDir] nor root directory is a git directory.

View File

@ -9,6 +9,7 @@ import 'package:pubspec_parse/pubspec_parse.dart';
import 'core.dart';
export 'package:pubspec_parse/pubspec_parse.dart' show Pubspec;
export 'core.dart' show FlutterPlatform;
/// A package in the repository.
//
@ -53,6 +54,44 @@ class RepositoryPackage {
/// The package's top-level README.
File get readmeFile => directory.childFile('README.md');
/// The package's top-level README.
File get changelogFile => directory.childFile('CHANGELOG.md');
/// The package's top-level README.
File get authorsFile => directory.childFile('AUTHORS');
/// The lib directory containing the package's code.
Directory get libDirectory => directory.childDirectory('lib');
/// The test directory containing the package's Dart tests.
Directory get testDirectory => directory.childDirectory('test');
/// Returns the directory containing support for [platform].
Directory platformDirectory(FlutterPlatform platform) {
late final String directoryName;
switch (platform) {
case FlutterPlatform.android:
directoryName = 'android';
break;
case FlutterPlatform.ios:
directoryName = 'ios';
break;
case FlutterPlatform.linux:
directoryName = 'linux';
break;
case FlutterPlatform.macos:
directoryName = 'macos';
break;
case FlutterPlatform.web:
directoryName = 'web';
break;
case FlutterPlatform.windows:
directoryName = 'windows';
break;
}
return directory.childDirectory(directoryName);
}
late final Pubspec _parsedPubspec =
Pubspec.parse(pubspecFile.readAsStringSync());

View File

@ -30,11 +30,14 @@ class CreateAllPluginsAppCommand extends PluginCommand {
'Defaults to the repository root.');
}
/// The location of the synthesized app project.
Directory get appDirectory => packagesDir.fileSystem
/// The location to create the synthesized app project.
Directory get _appDirectory => packagesDir.fileSystem
.directory(getStringArg(_outputDirectoryFlag))
.childDirectory('all_plugins');
/// The synthesized app project.
RepositoryPackage get app => RepositoryPackage(_appDirectory);
@override
String get description =>
'Generate Flutter app that includes all plugins in packages.';
@ -73,7 +76,7 @@ class CreateAllPluginsAppCommand extends PluginCommand {
'--template=app',
'--project-name=all_plugins',
'--android-language=java',
appDirectory.path,
_appDirectory.path,
],
);
@ -83,8 +86,8 @@ class CreateAllPluginsAppCommand extends PluginCommand {
}
Future<void> _updateAppGradle() async {
final File gradleFile = appDirectory
.childDirectory('android')
final File gradleFile = app
.platformDirectory(FlutterPlatform.android)
.childDirectory('app')
.childFile('build.gradle');
if (!gradleFile.existsSync()) {
@ -119,8 +122,8 @@ class CreateAllPluginsAppCommand extends PluginCommand {
}
Future<void> _updateManifest() async {
final File manifestFile = appDirectory
.childDirectory('android')
final File manifestFile = app
.platformDirectory(FlutterPlatform.android)
.childDirectory('app')
.childDirectory('src')
.childDirectory('main')
@ -147,12 +150,11 @@ class CreateAllPluginsAppCommand extends PluginCommand {
}
Future<void> _genPubspecWithAllPlugins() async {
final RepositoryPackage buildAllApp = RepositoryPackage(appDirectory);
// Read the old pubspec file's Dart SDK version, in order to preserve it
// in the new file. The template sometimes relies on having opted in to
// specific language features via SDK version, so using a different one
// can cause compilation failures.
final Pubspec originalPubspec = buildAllApp.parsePubspec();
final Pubspec originalPubspec = app.parsePubspec();
const String dartSdkKey = 'sdk';
final VersionConstraint dartSdkConstraint =
originalPubspec.environment?[dartSdkKey] ??
@ -177,7 +179,7 @@ class CreateAllPluginsAppCommand extends PluginCommand {
},
dependencyOverrides: pluginDeps,
);
buildAllApp.pubspecFile.writeAsStringSync(_pubspecToString(pubspec));
app.pubspecFile.writeAsStringSync(_pubspecToString(pubspec));
}
Future<Map<String, PathDependency>> _getValidPathDependencies() async {

View File

@ -146,7 +146,7 @@ class FirebaseTestLabCommand extends PackageLoopingCommand {
required RepositoryPackage package,
}) async {
final Directory androidDirectory =
example.directory.childDirectory('android');
example.platformDirectory(FlutterPlatform.android);
if (!androidDirectory.existsSync()) {
return PackageResult.skip(
'${example.displayName} does not support Android.');
@ -171,7 +171,7 @@ class FirebaseTestLabCommand extends PackageLoopingCommand {
}
// Ensures that gradle wrapper exists
final GradleProject project = GradleProject(example.directory,
final GradleProject project = GradleProject(example,
processRunner: processRunner, platform: platform);
if (!await _ensureGradleWrapperExists(project)) {
return PackageResult.fail(<String>['Unable to build example apk']);

View File

@ -40,7 +40,7 @@ class LintAndroidCommand extends PackageLoopingCommand {
bool failed = false;
for (final RepositoryPackage example in package.getExamples()) {
final GradleProject project = GradleProject(example.directory,
final GradleProject project = GradleProject(example,
processRunner: processRunner, platform: platform);
if (!project.isConfigured()) {

View File

@ -178,7 +178,7 @@ dependency_overrides:
for (final String packageName in packagesToOverride) {
// Find the relative path from the common base to the local package.
final List<String> repoRelativePathComponents = path.split(
path.relative(localDependencies[packageName]!.directory.path,
path.relative(localDependencies[packageName]!.path,
from: commonBasePath));
newPubspecContents += '''
$packageName:

View File

@ -198,22 +198,22 @@ this command.
Future<_PlatformResult> _testAndroid(
RepositoryPackage plugin, _TestMode mode) async {
bool exampleHasUnitTests(RepositoryPackage example) {
return example.directory
.childDirectory('android')
return example
.platformDirectory(FlutterPlatform.android)
.childDirectory('app')
.childDirectory('src')
.childDirectory('test')
.existsSync() ||
example.directory.parent
.childDirectory('android')
plugin
.platformDirectory(FlutterPlatform.android)
.childDirectory('src')
.childDirectory('test')
.existsSync();
}
bool exampleHasNativeIntegrationTests(RepositoryPackage example) {
final Directory integrationTestDirectory = example.directory
.childDirectory('android')
final Directory integrationTestDirectory = example
.platformDirectory(FlutterPlatform.android)
.childDirectory('app')
.childDirectory('src')
.childDirectory('androidTest');
@ -269,7 +269,7 @@ this command.
_printRunningExampleTestsMessage(example, 'Android');
final GradleProject project = GradleProject(
example.directory,
example,
processRunner: processRunner,
platform: platform,
);

View File

@ -246,12 +246,12 @@ HTTP response: ${pubVersionFinderResponse.httpResponse.body}
bool _passesAuthorsCheck(RepositoryPackage package) {
final List<String> pathComponents =
package.directory.fileSystem.path.split(package.directory.path);
package.directory.fileSystem.path.split(package.path);
if (pathComponents.contains('third_party')) {
// Third-party packages aren't required to have an AUTHORS file.
return true;
}
return package.directory.childFile('AUTHORS').existsSync();
return package.authorsFile.existsSync();
}
void _printImportantStatusMessage(String message, {required bool isError}) {

View File

@ -41,7 +41,7 @@ class TestCommand extends PackageLoopingCommand {
@override
Future<PackageResult> runForPackage(RepositoryPackage package) async {
if (!package.directory.childDirectory('test').existsSync()) {
if (!package.testDirectory.existsSync()) {
return PackageResult.skip('No test/ directory.');
}

View File

@ -384,7 +384,7 @@ ${indentation}HTTP response: ${pubVersionFinderResponse.httpResponse.body}
final Version fromPubspec = pubspec.version!;
// get first version from CHANGELOG
final File changelog = package.directory.childFile('CHANGELOG.md');
final File changelog = package.changelogFile;
final List<String> lines = changelog.readAsLinesSync();
String? firstLineWithText;
final Iterator<String> iterator = lines.iterator;