[flutter_tools] ensure pub get can run from partially valid state (#74249)
This commit is contained in:
parent
7a413e715f
commit
a0be98020e
@ -76,6 +76,8 @@ class PackagesGetCommand extends FlutterCommand {
|
||||
return '${runner.executableName} pub $name [<target directory>]';
|
||||
}
|
||||
|
||||
/// The pub packages usage values are incorrect since these are calculated/sent
|
||||
/// before pub get completes. This needs to be performed after dependency resolution.
|
||||
@override
|
||||
Future<Map<CustomDimensions, String>> get usageValues async {
|
||||
final Map<CustomDimensions, String> usageValues = <CustomDimensions, String>{};
|
||||
@ -85,9 +87,14 @@ class PackagesGetCommand extends FlutterCommand {
|
||||
return usageValues;
|
||||
}
|
||||
final FlutterProject rootProject = FlutterProject.fromPath(target);
|
||||
final bool hasPlugins = rootProject.flutterPluginsDependenciesFile.existsSync();
|
||||
// Do not send plugin analytics if pub has not run before.
|
||||
final bool hasPlugins = rootProject.flutterPluginsDependenciesFile.existsSync()
|
||||
&& rootProject.packagesFile.existsSync()
|
||||
&& rootProject.packageConfigFile.existsSync();
|
||||
if (hasPlugins) {
|
||||
final List<Plugin> plugins = await findPlugins(rootProject);
|
||||
// Do not fail pub get if package config files are invalid before pub has
|
||||
// had a chance to run.
|
||||
final List<Plugin> plugins = await findPlugins(rootProject, throwOnError: false);
|
||||
usageValues[CustomDimensions.commandPackagesNumberPlugins] = plugins.length.toString();
|
||||
} else {
|
||||
usageValues[CustomDimensions.commandPackagesNumberPlugins] = '0';
|
||||
|
@ -345,7 +345,7 @@ Plugin _pluginFromPackage(String name, Uri packageRoot) {
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<Plugin>> findPlugins(FlutterProject project) async {
|
||||
Future<List<Plugin>> findPlugins(FlutterProject project, { bool throwOnError = true}) async {
|
||||
final List<Plugin> plugins = <Plugin>[];
|
||||
final String packagesFile = globals.fs.path.join(
|
||||
project.directory.path,
|
||||
@ -354,6 +354,7 @@ Future<List<Plugin>> findPlugins(FlutterProject project) async {
|
||||
final PackageConfig packageConfig = await loadPackageConfigWithLogging(
|
||||
globals.fs.file(packagesFile),
|
||||
logger: globals.logger,
|
||||
throwOnError: throwOnError,
|
||||
);
|
||||
for (final Package package in packageConfig.packages) {
|
||||
final Uri packageRoot = package.packageUriRoot.resolve('..');
|
||||
|
@ -162,6 +162,12 @@ class FlutterProject {
|
||||
/// The `.packages` file of this project.
|
||||
File get packagesFile => directory.childFile('.packages');
|
||||
|
||||
/// The `package_config.json` file of the project.
|
||||
///
|
||||
/// This is the replacement for .packages which contains language
|
||||
/// version information.
|
||||
File get packageConfigFile => directory.childDirectory('.dart_tool').childFile('package_config.json');
|
||||
|
||||
/// The `.metadata` file of this project.
|
||||
File get metadataFile => directory.childFile('.metadata');
|
||||
|
||||
|
@ -0,0 +1,101 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/commands/packages.dart';
|
||||
import 'package:flutter_tools/src/dart/pub.dart';
|
||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:test/fake.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
|
||||
void main() {
|
||||
FileSystem fileSystem;
|
||||
FakePub pub;
|
||||
|
||||
setUp(() {
|
||||
Cache.disableLocking();
|
||||
fileSystem = MemoryFileSystem.test();
|
||||
pub = FakePub(fileSystem);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
Cache.enableLocking();
|
||||
});
|
||||
|
||||
testUsingContext('pub get usage values are resilient to missing package config files before running "pub get"', () async {
|
||||
fileSystem.currentDirectory.childFile('pubspec.yaml').createSync();
|
||||
fileSystem.currentDirectory.childFile('.flutter-plugins').createSync();
|
||||
fileSystem.currentDirectory.childFile('.flutter-plugins-dependencies').createSync();
|
||||
|
||||
final PackagesGetCommand command = PackagesGetCommand('get', false);
|
||||
final CommandRunner<void> commandRunner = createTestCommandRunner(command);
|
||||
|
||||
await commandRunner.run(<String>['get']);
|
||||
|
||||
expect(await command.usageValues, <CustomDimensions, Object>{
|
||||
CustomDimensions.commandPackagesNumberPlugins: '0',
|
||||
CustomDimensions.commandPackagesProjectModule: 'false',
|
||||
CustomDimensions.commandPackagesAndroidEmbeddingVersion: 'v1'
|
||||
});
|
||||
}, overrides: <Type, Generator>{
|
||||
Pub: () => pub,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
FileSystem: () => fileSystem,
|
||||
});
|
||||
|
||||
testUsingContext('pub get usage values are resilient to poorly formatted package config before "pub get"', () async {
|
||||
fileSystem.currentDirectory.childFile('pubspec.yaml').createSync();
|
||||
fileSystem.currentDirectory.childFile('.flutter-plugins').createSync();
|
||||
fileSystem.currentDirectory.childFile('.flutter-plugins-dependencies').createSync();
|
||||
fileSystem.currentDirectory.childFile('.packages').writeAsBytesSync(<int>[0]);
|
||||
fileSystem.currentDirectory.childFile('.dart_tool/package_config.json')
|
||||
..createSync(recursive: true)
|
||||
..writeAsBytesSync(<int>[0]);
|
||||
|
||||
final PackagesGetCommand command = PackagesGetCommand('get', false);
|
||||
final CommandRunner<void> commandRunner = createTestCommandRunner(command);
|
||||
|
||||
await commandRunner.run(<String>['get']);
|
||||
|
||||
expect(await command.usageValues, <CustomDimensions, Object>{
|
||||
CustomDimensions.commandPackagesNumberPlugins: '0',
|
||||
CustomDimensions.commandPackagesProjectModule: 'false',
|
||||
CustomDimensions.commandPackagesAndroidEmbeddingVersion: 'v1'
|
||||
});
|
||||
}, overrides: <Type, Generator>{
|
||||
Pub: () => pub,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
FileSystem: () => fileSystem,
|
||||
});
|
||||
}
|
||||
|
||||
class FakePub extends Fake implements Pub {
|
||||
FakePub(this.fileSystem);
|
||||
|
||||
final FileSystem fileSystem;
|
||||
|
||||
@override
|
||||
Future<void> get({
|
||||
@required PubContext context,
|
||||
String directory,
|
||||
bool skipIfAbsent = false,
|
||||
bool upgrade = false,
|
||||
bool offline = false,
|
||||
bool generateSyntheticPackage = false,
|
||||
String flutterRootOverride,
|
||||
bool checkUpToDate = false,
|
||||
}) async {
|
||||
fileSystem.currentDirectory
|
||||
.childDirectory('.dart_tool')
|
||||
.childFile('package_config.json')
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('{"configVersion":2,"packages":[]}');
|
||||
}
|
||||
}
|
@ -8,10 +8,10 @@ import 'package:flutter_tools/src/base/io.dart';
|
||||
import '../src/common.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
/// Verifies that `dart migrate` will run successfuly on the default `flutter create`
|
||||
/// Verifies that `dart migrate` will run successfully on the default `flutter create`
|
||||
/// template.
|
||||
void main() {
|
||||
testWithoutContext('dart migrate succeedes on flutter create template', () async {
|
||||
testWithoutContext('dart migrate succeeds on flutter create template', () async {
|
||||
final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', platform.isWindows ? 'flutter.bat' : 'flutter');
|
||||
final String dartBin = fileSystem.path.join(getFlutterRoot(), 'bin', platform.isWindows ? 'dart.bat' : 'dart');
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user