Unverified Commit 76cbc462 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] remove all pub caching logic (#66776)

There have been some more additional reports of a missing 'package:characters' import after upgrading flutter, as well as problems with detecting the correct language version. This has me concerned that our pub caching logic is incorrect. Instead of the tool attempting to guess when pub should be run, always delegate to pub.
parent 826b7046
...@@ -700,8 +700,6 @@ class PubDependencies extends ArtifactSet { ...@@ -700,8 +700,6 @@ class PubDependencies extends ArtifactSet {
context: PubContext.pubGet, context: PubContext.pubGet,
directory: _fileSystem.path.join(_flutterRoot(), 'packages', 'flutter_tools'), directory: _fileSystem.path.join(_flutterRoot(), 'packages', 'flutter_tools'),
generateSyntheticPackage: false, generateSyntheticPackage: false,
skipPubspecYamlCheck: true,
checkLastModified: false,
); );
} }
} }
......
...@@ -117,7 +117,6 @@ class PackagesGetCommand extends FlutterCommand { ...@@ -117,7 +117,6 @@ class PackagesGetCommand extends FlutterCommand {
directory: directory, directory: directory,
upgrade: upgrade , upgrade: upgrade ,
offline: boolArg('offline'), offline: boolArg('offline'),
checkLastModified: false,
generateSyntheticPackage: flutterProject.manifest.generateSyntheticPackage, generateSyntheticPackage: flutterProject.manifest.generateSyntheticPackage,
); );
pubGetTimer.stop(); pubGetTimer.stop();
......
...@@ -8,11 +8,8 @@ import '../asset.dart'; ...@@ -8,11 +8,8 @@ import '../asset.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../build_system/build_system.dart';
import '../bundle.dart'; import '../bundle.dart';
import '../cache.dart'; import '../cache.dart';
import '../dart/generate_synthetic_packages.dart';
import '../dart/pub.dart';
import '../devfs.dart'; import '../devfs.dart';
import '../globals.dart' as globals; import '../globals.dart' as globals;
import '../project.dart'; import '../project.dart';
...@@ -169,32 +166,6 @@ class TestCommand extends FlutterCommand { ...@@ -169,32 +166,6 @@ class TestCommand extends FlutterCommand {
'directory (or one of its subdirectories).'); 'directory (or one of its subdirectories).');
} }
final FlutterProject flutterProject = FlutterProject.current(); final FlutterProject flutterProject = FlutterProject.current();
if (shouldRunPub) {
if (flutterProject.manifest.generateSyntheticPackage) {
final Environment environment = Environment(
artifacts: globals.artifacts,
logger: globals.logger,
cacheDir: globals.cache.getRoot(),
engineVersion: globals.flutterVersion.engineRevision,
fileSystem: globals.fs,
flutterRootDir: globals.fs.directory(Cache.flutterRoot),
outputDir: globals.fs.directory(getBuildDirectory()),
processManager: globals.processManager,
projectDir: flutterProject.directory,
);
await generateLocalizationsSyntheticPackage(
environment: environment,
buildSystem: globals.buildSystem,
);
}
await pub.get(
context: PubContext.getVerifyContext(name),
skipPubspecYamlCheck: true,
generateSyntheticPackage: flutterProject.manifest.generateSyntheticPackage,
);
}
final bool buildTestAssets = boolArg('test-assets'); final bool buildTestAssets = boolArg('test-assets');
final List<String> names = stringsArg('name'); final List<String> names = stringsArg('name');
final List<String> plainNames = stringsArg('plain-name'); final List<String> plainNames = stringsArg('plain-name');
......
...@@ -330,7 +330,6 @@ class UpdatePackagesCommand extends FlutterCommand { ...@@ -330,7 +330,6 @@ class UpdatePackagesCommand extends FlutterCommand {
context: PubContext.updatePackages, context: PubContext.updatePackages,
directory: tempDir.path, directory: tempDir.path,
upgrade: true, upgrade: true,
checkLastModified: false,
offline: offline, offline: offline,
flutterRootOverride: upgrade flutterRootOverride: upgrade
? temporaryFlutterSdk.path ? temporaryFlutterSdk.path
...@@ -413,7 +412,6 @@ class UpdatePackagesCommand extends FlutterCommand { ...@@ -413,7 +412,6 @@ class UpdatePackagesCommand extends FlutterCommand {
await pub.get( await pub.get(
context: PubContext.updatePackages, context: PubContext.updatePackages,
directory: dir.path, directory: dir.path,
checkLastModified: false,
offline: offline, offline: offline,
generateSyntheticPackage: false, generateSyntheticPackage: false,
); );
......
...@@ -296,7 +296,6 @@ class UpgradeCommandRunner { ...@@ -296,7 +296,6 @@ class UpgradeCommandRunner {
context: PubContext.pubUpgrade, context: PubContext.pubUpgrade,
directory: projectRoot, directory: projectRoot,
upgrade: true, upgrade: true,
checkLastModified: false,
generateSyntheticPackage: false, generateSyntheticPackage: false,
); );
} }
......
...@@ -151,7 +151,6 @@ class VersionCommand extends FlutterCommand { ...@@ -151,7 +151,6 @@ class VersionCommand extends FlutterCommand {
context: PubContext.pubUpgrade, context: PubContext.pubUpgrade,
directory: projectRoot, directory: projectRoot,
upgrade: true, upgrade: true,
checkLastModified: false,
generateSyntheticPackage: false, generateSyntheticPackage: false,
); );
} }
......
...@@ -236,8 +236,6 @@ Future<T> runInContext<T>( ...@@ -236,8 +236,6 @@ Future<T> runInContext<T>(
botDetector: globals.botDetector, botDetector: globals.botDetector,
platform: globals.platform, platform: globals.platform,
usage: globals.flutterUsage, usage: globals.flutterUsage,
// Avoid a circular dependency by making this access lazy.
toolStampFile: () => globals.cache.getStampFileFor('flutter_tools'),
), ),
ShutdownHooks: () => ShutdownHooks(logger: globals.logger), ShutdownHooks: () => ShutdownHooks(logger: globals.logger),
Stdio: () => Stdio(), Stdio: () => Stdio(),
......
...@@ -80,7 +80,6 @@ abstract class Pub { ...@@ -80,7 +80,6 @@ abstract class Pub {
@required Platform platform, @required Platform platform,
@required BotDetector botDetector, @required BotDetector botDetector,
@required Usage usage, @required Usage usage,
File Function() toolStampFile,
}) = _DefaultPub; }) = _DefaultPub;
/// Runs `pub get`. /// Runs `pub get`.
...@@ -93,8 +92,6 @@ abstract class Pub { ...@@ -93,8 +92,6 @@ abstract class Pub {
bool skipIfAbsent = false, bool skipIfAbsent = false,
bool upgrade = false, bool upgrade = false,
bool offline = false, bool offline = false,
bool checkLastModified = true,
bool skipPubspecYamlCheck = false,
bool generateSyntheticPackage = false, bool generateSyntheticPackage = false,
String flutterRootOverride, String flutterRootOverride,
}); });
...@@ -141,9 +138,7 @@ class _DefaultPub implements Pub { ...@@ -141,9 +138,7 @@ class _DefaultPub implements Pub {
@required Platform platform, @required Platform platform,
@required BotDetector botDetector, @required BotDetector botDetector,
@required Usage usage, @required Usage usage,
File Function() toolStampFile, }) : _fileSystem = fileSystem,
}) : _toolStampFile = toolStampFile,
_fileSystem = fileSystem,
_logger = logger, _logger = logger,
_platform = platform, _platform = platform,
_botDetector = botDetector, _botDetector = botDetector,
...@@ -159,7 +154,6 @@ class _DefaultPub implements Pub { ...@@ -159,7 +154,6 @@ class _DefaultPub implements Pub {
final Platform _platform; final Platform _platform;
final BotDetector _botDetector; final BotDetector _botDetector;
final Usage _usage; final Usage _usage;
final File Function() _toolStampFile;
@override @override
Future<void> get({ Future<void> get({
...@@ -168,33 +162,15 @@ class _DefaultPub implements Pub { ...@@ -168,33 +162,15 @@ class _DefaultPub implements Pub {
bool skipIfAbsent = false, bool skipIfAbsent = false,
bool upgrade = false, bool upgrade = false,
bool offline = false, bool offline = false,
bool checkLastModified = true,
bool skipPubspecYamlCheck = false,
bool generateSyntheticPackage = false, bool generateSyntheticPackage = false,
String flutterRootOverride, String flutterRootOverride,
}) async { }) async {
directory ??= _fileSystem.currentDirectory.path; directory ??= _fileSystem.currentDirectory.path;
final File pubSpecYaml = _fileSystem.file(
_fileSystem.path.join(directory, 'pubspec.yaml'));
final File packageConfigFile = _fileSystem.file( final File packageConfigFile = _fileSystem.file(
_fileSystem.path.join(directory, '.dart_tool', 'package_config.json')); _fileSystem.path.join(directory, '.dart_tool', 'package_config.json'));
final Directory generatedDirectory = _fileSystem.directory( final Directory generatedDirectory = _fileSystem.directory(
_fileSystem.path.join(directory, '.dart_tool', 'flutter_gen')); _fileSystem.path.join(directory, '.dart_tool', 'flutter_gen'));
if (!skipPubspecYamlCheck && !pubSpecYaml.existsSync()) {
if (!skipIfAbsent) {
throwToolExit('$directory: no pubspec.yaml found');
}
return;
}
final DateTime originalPubspecYamlModificationTime = pubSpecYaml.lastModifiedSync();
if (!checkLastModified || _shouldRunPubGet(
pubSpecYaml: pubSpecYaml,
packageConfigFile: packageConfigFile,
)) {
final String command = upgrade ? 'upgrade' : 'get'; final String command = upgrade ? 'upgrade' : 'get';
final Status status = _logger.startProgress( final Status status = _logger.startProgress(
'Running "flutter pub $command" in ${_fileSystem.path.basename(directory)}...', 'Running "flutter pub $command" in ${_fileSystem.path.basename(directory)}...',
...@@ -228,28 +204,10 @@ class _DefaultPub implements Pub { ...@@ -228,28 +204,10 @@ class _DefaultPub implements Pub {
status.cancel(); status.cancel();
rethrow; rethrow;
} }
}
if (!packageConfigFile.existsSync()) { if (!packageConfigFile.existsSync()) {
throwToolExit('$directory: pub did not create .dart_tools/package_config.json file.'); throwToolExit('$directory: pub did not create .dart_tools/package_config.json file.');
} }
if (pubSpecYaml.lastModifiedSync() != originalPubspecYamlModificationTime) {
throwToolExit(
'$directory: unexpected concurrent modification of '
'pubspec.yaml while running pub.');
}
// We don't check if dotPackages was actually modified, because as far as we can tell sometimes
// pub will decide it does not need to actually modify it.
final DateTime now = DateTime.now();
if (now.isBefore(originalPubspecYamlModificationTime)) {
_logger.printError(
'Warning: File "${_fileSystem.path.absolute(pubSpecYaml.path)}" was created in the future. '
'Optimizations that rely on comparing time stamps will be unreliable. Check your '
'system clock for accuracy.\n'
'The timestamp was: $originalPubspecYamlModificationTime\n'
'The time now is: $now'
);
}
await _updatePackageConfig( await _updatePackageConfig(
packageConfigFile, packageConfigFile,
generatedDirectory, generatedDirectory,
...@@ -392,23 +350,6 @@ class _DefaultPub implements Pub { ...@@ -392,23 +350,6 @@ class _DefaultPub implements Pub {
return <String>[sdkPath, ...arguments]; return <String>[sdkPath, ...arguments];
} }
bool _shouldRunPubGet({ @required File pubSpecYaml, @required File packageConfigFile }) {
if (!packageConfigFile.existsSync()) {
return true;
}
final DateTime dotPackagesLastModified = packageConfigFile.lastModifiedSync();
if (pubSpecYaml.lastModifiedSync().isAfter(dotPackagesLastModified)) {
return true;
}
final File toolStampFile = _toolStampFile != null ? _toolStampFile() : null;
if (toolStampFile != null &&
toolStampFile.existsSync() &&
toolStampFile.lastModifiedSync().isAfter(dotPackagesLastModified)) {
return true;
}
return false;
}
// Returns the environment value that should be used when running pub. // Returns the environment value that should be used when running pub.
// //
// Includes any existing environment variable, if one exists. // Includes any existing environment variable, if one exists.
......
...@@ -950,9 +950,9 @@ abstract class FlutterCommand extends Command<void> { ...@@ -950,9 +950,9 @@ abstract class FlutterCommand extends Command<void> {
// First always update universal artifacts, as some of these (e.g. // First always update universal artifacts, as some of these (e.g.
// ios-deploy on macOS) are required to determine `requiredArtifacts`. // ios-deploy on macOS) are required to determine `requiredArtifacts`.
await globals.cache.updateAll(<DevelopmentArtifact>{DevelopmentArtifact.universal}); await globals.cache.updateAll(<DevelopmentArtifact>{DevelopmentArtifact.universal});
await globals.cache.updateAll(await requiredArtifacts); await globals.cache.updateAll(await requiredArtifacts);
} }
Cache.releaseLock();
await validateCommand(); await validateCommand();
...@@ -979,11 +979,7 @@ abstract class FlutterCommand extends Command<void> { ...@@ -979,11 +979,7 @@ abstract class FlutterCommand extends Command<void> {
context: PubContext.getVerifyContext(name), context: PubContext.getVerifyContext(name),
generateSyntheticPackage: project.manifest.generateSyntheticPackage, generateSyntheticPackage: project.manifest.generateSyntheticPackage,
); );
// All done updating dependencies. Release the cache lock.
Cache.releaseLock();
await project.ensureReadyForPlatformSpecificTooling(checkProjects: true); await project.ensureReadyForPlatformSpecificTooling(checkProjects: true);
} else {
Cache.releaseLock();
} }
setupApplicationPackages(); setupApplicationPackages();
......
...@@ -743,9 +743,6 @@ void main() { ...@@ -743,9 +743,6 @@ void main() {
verify(pub.get( verify(pub.get(
context: PubContext.pubGet, context: PubContext.pubGet,
directory: 'packages/flutter_tools', directory: 'packages/flutter_tools',
generateSyntheticPackage: false,
skipPubspecYamlCheck: true,
checkLastModified: false,
)).called(1); )).called(1);
}); });
} }
......
...@@ -49,7 +49,7 @@ void main() { ...@@ -49,7 +49,7 @@ void main() {
FakeAsync().run((FakeAsync time) { FakeAsync().run((FakeAsync time) {
expect(processMock.lastPubEnvironment, isNull); expect(processMock.lastPubEnvironment, isNull);
expect(logger.statusText, ''); expect(logger.statusText, '');
pub.get(context: PubContext.flutterTests, checkLastModified: false).then((void value) { pub.get(context: PubContext.flutterTests).then((void value) {
error = 'test completed unexpectedly'; error = 'test completed unexpectedly';
}, onError: (dynamic thrownError) { }, onError: (dynamic thrownError) {
error = 'test failed unexpectedly: $thrownError'; error = 'test failed unexpectedly: $thrownError';
...@@ -114,7 +114,7 @@ void main() { ...@@ -114,7 +114,7 @@ void main() {
processManager: MockProcessManager(66, stderr: 'err1\nerr2\nerr3\n', stdout: 'out1\nout2\nout3\n'), processManager: MockProcessManager(66, stderr: 'err1\nerr2\nerr3\n', stdout: 'out1\nout2\nout3\n'),
); );
try { try {
await pub.get(context: PubContext.flutterTests, checkLastModified: false); await pub.get(context: PubContext.flutterTests);
throw AssertionError('pubGet did not fail'); throw AssertionError('pubGet did not fail');
} on ToolExit catch (error) { } on ToolExit catch (error) {
expect(error.message, 'pub get failed (66; err3)'); expect(error.message, 'pub get failed (66; err3)');
...@@ -149,7 +149,7 @@ void main() { ...@@ -149,7 +149,7 @@ void main() {
MockDirectory.findCache = true; MockDirectory.findCache = true;
expect(processMock.lastPubEnvironment, isNull); expect(processMock.lastPubEnvironment, isNull);
expect(processMock.lastPubCache, isNull); expect(processMock.lastPubCache, isNull);
pub.get(context: PubContext.flutterTests, checkLastModified: false).then((void value) { pub.get(context: PubContext.flutterTests).then((void value) {
error = 'test completed unexpectedly'; error = 'test completed unexpectedly';
}, onError: (dynamic thrownError) { }, onError: (dynamic thrownError) {
error = 'test failed unexpectedly: $thrownError'; error = 'test failed unexpectedly: $thrownError';
...@@ -182,7 +182,7 @@ void main() { ...@@ -182,7 +182,7 @@ void main() {
expect(processMock.lastPubCache, isNull); expect(processMock.lastPubCache, isNull);
String error; String error;
pub.get(context: PubContext.flutterTests, checkLastModified: false).then((void value) { pub.get(context: PubContext.flutterTests).then((void value) {
error = 'test completed unexpectedly'; error = 'test completed unexpectedly';
}, onError: (dynamic thrownError) { }, onError: (dynamic thrownError) {
error = 'test failed unexpectedly: $thrownError'; error = 'test failed unexpectedly: $thrownError';
...@@ -217,7 +217,6 @@ void main() { ...@@ -217,7 +217,6 @@ void main() {
await pub.get( await pub.get(
context: PubContext.flutterTests, context: PubContext.flutterTests,
generateSyntheticPackage: true, generateSyntheticPackage: true,
checkLastModified: false,
); );
verify(usage.sendEvent('pub-result', 'flutter-tests', label: 'success')).called(1); verify(usage.sendEvent('pub-result', 'flutter-tests', label: 'success')).called(1);
...@@ -255,7 +254,6 @@ void main() { ...@@ -255,7 +254,6 @@ void main() {
await pub.get( await pub.get(
context: PubContext.flutterTests, context: PubContext.flutterTests,
generateSyntheticPackage: true, generateSyntheticPackage: true,
checkLastModified: false,
); );
expect( expect(
...@@ -285,7 +283,7 @@ void main() { ...@@ -285,7 +283,7 @@ void main() {
), ),
); );
try { try {
await pub.get(context: PubContext.flutterTests, checkLastModified: false); await pub.get(context: PubContext.flutterTests);
} on ToolExit { } on ToolExit {
// Ignore. // Ignore.
} }
...@@ -314,7 +312,7 @@ void main() { ...@@ -314,7 +312,7 @@ void main() {
fileSystem.file('pubspec.yaml').writeAsStringSync('name: foo'); fileSystem.file('pubspec.yaml').writeAsStringSync('name: foo');
try { try {
await pub.get(context: PubContext.flutterTests, checkLastModified: false); await pub.get(context: PubContext.flutterTests);
} on ToolExit { } on ToolExit {
// Ignore. // Ignore.
} }
...@@ -386,7 +384,7 @@ void main() { ...@@ -386,7 +384,7 @@ void main() {
fileSystem.file('pubspec.yaml') fileSystem.file('pubspec.yaml')
..createSync() ..createSync()
..setLastModifiedSync(DateTime(2001)); ..setLastModifiedSync(DateTime(2001));
await pub.get(context: PubContext.flutterTests, checkLastModified: true); // pub sets date of .packages to 2002 await pub.get(context: PubContext.flutterTests); // pub sets date of .packages to 2002
expect(logger.statusText, 'Running "flutter pub get" in /...\n'); expect(logger.statusText, 'Running "flutter pub get" in /...\n');
expect(logger.errorText, isEmpty); expect(logger.errorText, isEmpty);
...@@ -398,44 +396,12 @@ void main() { ...@@ -398,44 +396,12 @@ void main() {
.setLastModifiedSync(DateTime(2000)); .setLastModifiedSync(DateTime(2000));
fileSystem.file('pubspec.yaml') fileSystem.file('pubspec.yaml')
.setLastModifiedSync(DateTime(2001)); .setLastModifiedSync(DateTime(2001));
await pub.get(context: PubContext.flutterTests, checkLastModified: true); // pub does nothing await pub.get(context: PubContext.flutterTests); // pub does nothing
expect(logger.statusText, 'Running "flutter pub get" in /...\n'); expect(logger.statusText, 'Running "flutter pub get" in /...\n');
expect(logger.errorText, isEmpty); expect(logger.errorText, isEmpty);
expect(fileSystem.file('pubspec.yaml').lastModifiedSync(), DateTime(2001)); // because nothing should touch it expect(fileSystem.file('pubspec.yaml').lastModifiedSync(), DateTime(2001)); // because nothing should touch it
logger.clear(); logger.clear();
// bad scenario 2: pub changes pubspec.yaml instead
fileSystem.file('.dart_tool/package_config.json')
.setLastModifiedSync(DateTime(2000));
fileSystem.file('pubspec.yaml')
.setLastModifiedSync(DateTime(2001));
try {
await pub.get(context: PubContext.flutterTests, checkLastModified: true);
expect(true, isFalse, reason: 'pub.get did not throw');
} on ToolExit catch (error) {
expect(error.message, '/: unexpected concurrent modification of pubspec.yaml while running pub.');
}
expect(logger.statusText, 'Running "flutter pub get" in /...\n');
expect(logger.errorText, isEmpty);
expect(fileSystem.file('pubspec.yaml').lastModifiedSync(), DateTime(2002)); // because fake pub above touched it
// bad scenario 3: pubspec.yaml was created in the future
fileSystem.file('.dart_tool/package_config.json')
.setLastModifiedSync(DateTime(2000));
fileSystem.file('pubspec.yaml')
.setLastModifiedSync(DateTime(9999));
assert(DateTime(9999).isAfter(DateTime.now()));
await pub.get(context: PubContext.flutterTests, checkLastModified: true); // pub does nothing
expect(logger.statusText, contains('Running "flutter pub get" in /...\n'));
expect(logger.errorText, startsWith(
'Warning: File "/pubspec.yaml" was created in the future. Optimizations that rely on '
'comparing time stamps will be unreliable. Check your system clock for accuracy.\n'
'The timestamp was:'
));
logger.clear();
}); });
} }
......
...@@ -24,7 +24,8 @@ final ProcessUtils processUtils = ProcessUtils(processManager: processManager, l ...@@ -24,7 +24,8 @@ final ProcessUtils processUtils = ProcessUtils(processManager: processManager, l
outputPreferences: OutputPreferences.test(wrapText: true), outputPreferences: OutputPreferences.test(wrapText: true),
timeoutConfiguration: const TimeoutConfiguration(), timeoutConfiguration: const TimeoutConfiguration(),
)); ));
final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter'); 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');
/// A test for flutter upgrade & downgrade that checks out a parallel flutter repo. /// A test for flutter upgrade & downgrade that checks out a parallel flutter repo.
void main() { void main() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment