[flutter_plugin_tools] Fix subpackage analysis (#5027)

This commit is contained in:
stuartmorgan
2022-03-11 15:15:26 -05:00
committed by GitHub
parent 159f6d87b7
commit 1bbfb60816
7 changed files with 103 additions and 18 deletions

View File

@ -1,3 +1,8 @@
## 0.8.1
- Fixes an `analyze` regression in 0.8.0 with packages that have non-`example`
sub-packages.
## 0.8.0 ## 0.8.0
- Ensures that `firebase-test-lab` runs include an `integration_test` runner. - Ensures that `firebase-test-lab` runs include an `integration_test` runner.

View File

@ -102,18 +102,27 @@ class AnalyzeCommand extends PackageLoopingCommand {
@override @override
Future<PackageResult> runForPackage(RepositoryPackage package) async { Future<PackageResult> runForPackage(RepositoryPackage package) async {
// For non-example packages, fetch dependencies. 'flutter packages get' // Analysis runs over the package and all subpackages, so all of them need
// automatically runs 'pub get' in examples as part of handling the parent // `flutter packages get` run before analyzing. `example` packages can be
// directory, which is guaranteed to come first in the package enumeration. // skipped since 'flutter packages get' automatically runs `pub get` in
if (package.directory.basename != 'example' || // examples as part of handling the parent directory.
!RepositoryPackage(package.directory.parent).pubspecFile.existsSync()) { final List<RepositoryPackage> packagesToGet = <RepositoryPackage>[
package,
...await getSubpackages(package).toList(),
];
for (final RepositoryPackage packageToGet in packagesToGet) {
if (packageToGet.directory.basename != 'example' ||
!RepositoryPackage(packageToGet.directory.parent)
.pubspecFile
.existsSync()) {
final int exitCode = await processRunner.runAndStream( final int exitCode = await processRunner.runAndStream(
flutterCommand, <String>['packages', 'get'], flutterCommand, <String>['packages', 'get'],
workingDir: package.directory); workingDir: packageToGet.directory);
if (exitCode != 0) { if (exitCode != 0) {
return PackageResult.fail(<String>['Unable to get dependencies']); return PackageResult.fail(<String>['Unable to get dependencies']);
} }
} }
}
if (_hasUnexpecetdAnalysisOptions(package)) { if (_hasUnexpecetdAnalysisOptions(package)) {
return PackageResult.fail(<String>['Unexpected local analysis options']); return PackageResult.fail(<String>['Unexpected local analysis options']);

View File

@ -417,14 +417,20 @@ abstract class PluginCommand extends Command<void> {
await for (final PackageEnumerationEntry plugin await for (final PackageEnumerationEntry plugin
in getTargetPackages(filterExcluded: filterExcluded)) { in getTargetPackages(filterExcluded: filterExcluded)) {
yield plugin; yield plugin;
yield* plugin.package.directory yield* getSubpackages(plugin.package).map((RepositoryPackage package) =>
PackageEnumerationEntry(package, excluded: plugin.excluded));
}
}
/// Returns all Dart package folders (e.g., examples) under the given package.
Stream<RepositoryPackage> getSubpackages(RepositoryPackage package,
{bool filterExcluded = true}) async* {
yield* package.directory
.list(recursive: true, followLinks: false) .list(recursive: true, followLinks: false)
.where(_isDartPackage) .where(_isDartPackage)
.map((FileSystemEntity directory) => PackageEnumerationEntry( .map((FileSystemEntity directory) =>
// _isDartPackage guarantees that this cast is valid. // _isDartPackage guarantees that this cast is valid.
RepositoryPackage(directory as Directory), RepositoryPackage(directory as Directory));
excluded: plugin.excluded));
}
} }
/// Returns the files contained, recursively, within the packages /// Returns the files contained, recursively, within the packages

View File

@ -207,6 +207,10 @@ dependency_overrides:
allComponents.contains('example')) { allComponents.contains('example')) {
continue; continue;
} }
if (!allComponents.contains(packagesDir.basename)) {
print(' Skipping $changedPath; not in packages directory.');
continue;
}
final RepositoryPackage package = final RepositoryPackage package =
RepositoryPackage(packagesDir.fileSystem.file(changedPath).parent); RepositoryPackage(packagesDir.fileSystem.file(changedPath).parent);
// Ignored deleted packages, as they won't be published. // Ignored deleted packages, as they won't be published.

View File

@ -1,7 +1,7 @@
name: flutter_plugin_tools name: flutter_plugin_tools
description: Productivity utils for flutter/plugins and flutter/packages description: Productivity utils for flutter/plugins and flutter/packages
repository: https://github.com/flutter/plugins/tree/main/script/tool repository: https://github.com/flutter/plugins/tree/main/script/tool
version: 0.8.0 version: 0.8.1
dependencies: dependencies:
args: ^2.1.0 args: ^2.1.0

View File

@ -71,6 +71,31 @@ void main() {
])); ]));
}); });
test('runs flutter pub get for non-example subpackages', () async {
final Directory mainPackageDir = createFakePackage('a', packagesDir);
final Directory otherPackages =
mainPackageDir.childDirectory('other_packages');
final Directory subpackage1 =
createFakePackage('subpackage1', otherPackages);
final Directory subpackage2 =
createFakePackage('subpackage2', otherPackages);
await runCapturingPrint(runner, <String>['analyze']);
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall('flutter', const <String>['packages', 'get'],
mainPackageDir.path),
ProcessCall(
'flutter', const <String>['packages', 'get'], subpackage1.path),
ProcessCall(
'flutter', const <String>['packages', 'get'], subpackage2.path),
ProcessCall('dart', const <String>['analyze', '--fatal-infos'],
mainPackageDir.path),
]));
});
test('don\'t elide a non-contained example package', () async { test('don\'t elide a non-contained example package', () async {
final Directory plugin1Dir = createFakePlugin('a', packagesDir); final Directory plugin1Dir = createFakePlugin('a', packagesDir);
final Directory plugin2Dir = createFakePlugin('example', packagesDir); final Directory plugin2Dir = createFakePlugin('example', packagesDir);

View File

@ -323,5 +323,41 @@ void main() {
]), ]),
); );
}); });
test('skips anything outside of the packages directory', () async {
final Directory toolDir = packagesDir.parent.childDirectory('tool');
const String newVersion = '1.1.0';
final Directory package = createFakePackage(
'flutter_plugin_tools', toolDir,
version: newVersion);
// Simulate a minor version change so it would be a target.
final File pubspecFile = RepositoryPackage(package).pubspecFile;
final String changedFileOutput = <File>[
pubspecFile,
].map((File file) => file.path).join('\n');
processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
MockProcess(stdout: changedFileOutput),
];
final String gitPubspecContents =
pubspecFile.readAsStringSync().replaceAll(newVersion, '1.0.0');
processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
MockProcess(stdout: gitPubspecContents),
];
final List<String> output = await runCapturingPrint(runner, <String>[
'make-deps-path-based',
'--target-dependencies-with-non-breaking-updates'
]);
expect(
output,
containsAllInOrder(<Matcher>[
contains(
'Skipping /tool/flutter_plugin_tools/pubspec.yaml; not in packages directory.'),
contains('No target dependencies'),
]),
);
});
}); });
} }