Unverified Commit ff953e4f authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] restore pub caching functionality (#70133)

Necessary to work around #70013 (this looks like it will be fixed, but should protect us in the future)

Restores some notion of skipping pub, with differences from the prior implementation:

Off by default, and only used by the flutter command automatic pub get
A single check parameter. Uses the framework version cached per-project instead of a timestamp of the tool, to avoid cases where downloading a prebuilt framework would cause this check to no longer work.
parent bbc01616
...@@ -94,6 +94,7 @@ abstract class Pub { ...@@ -94,6 +94,7 @@ abstract class Pub {
bool offline = false, bool offline = false,
bool generateSyntheticPackage = false, bool generateSyntheticPackage = false,
String flutterRootOverride, String flutterRootOverride,
bool checkUpToDate = false,
}); });
/// Runs pub in 'batch' mode. /// Runs pub in 'batch' mode.
...@@ -118,7 +119,6 @@ abstract class Pub { ...@@ -118,7 +119,6 @@ abstract class Pub {
bool showTraceForErrors, bool showTraceForErrors,
}); });
/// Runs pub in 'interactive' mode. /// Runs pub in 'interactive' mode.
/// ///
/// directly piping the stdin stream of this process to that of pub, and the /// directly piping the stdin stream of this process to that of pub, and the
...@@ -164,12 +164,38 @@ class _DefaultPub implements Pub { ...@@ -164,12 +164,38 @@ class _DefaultPub implements Pub {
bool offline = false, bool offline = false,
bool generateSyntheticPackage = false, bool generateSyntheticPackage = false,
String flutterRootOverride, String flutterRootOverride,
bool checkUpToDate = false,
}) async { }) async {
directory ??= _fileSystem.currentDirectory.path; directory ??= _fileSystem.currentDirectory.path;
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'));
final File lastVersion = _fileSystem.file(
_fileSystem.path.join(directory, '.dart_tool', 'version'));
final File currentVersion = _fileSystem.file(
_fileSystem.path.join(Cache.flutterRoot, 'version'));
final File pubspecYaml = _fileSystem.file(
_fileSystem.path.join(directory, 'pubspec.yaml'));
final File pubLockFile = _fileSystem.file(
_fileSystem.path.join(directory, 'pubspec.lock')
);
// If the pubspec.yaml is older than the package config file and the last
// flutter version used is the same as the current version skip pub get.
// This will incorrectly skip pub on the master branch if dependencies
// are being added/removed from the flutter framework packages, but this
// can be worked around by manually running pub.
if (checkUpToDate &&
packageConfigFile.existsSync() &&
pubLockFile.existsSync() &&
pubspecYaml.lastModifiedSync().isBefore(pubLockFile.lastModifiedSync()) &&
pubspecYaml.lastModifiedSync().isBefore(packageConfigFile.lastModifiedSync()) &&
lastVersion.existsSync() &&
lastVersion.readAsStringSync() == currentVersion.readAsStringSync()) {
_logger.printTrace('Skipping pub get: version match.');
return;
}
final String command = upgrade ? 'upgrade' : 'get'; final String command = upgrade ? 'upgrade' : 'get';
final Status status = _logger.startProgress( final Status status = _logger.startProgress(
...@@ -207,6 +233,7 @@ class _DefaultPub implements Pub { ...@@ -207,6 +233,7 @@ class _DefaultPub implements Pub {
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.');
} }
lastVersion.writeAsStringSync(currentVersion.readAsStringSync());
await _updatePackageConfig( await _updatePackageConfig(
packageConfigFile, packageConfigFile,
generatedDirectory, generatedDirectory,
......
...@@ -1061,6 +1061,7 @@ abstract class FlutterCommand extends Command<void> { ...@@ -1061,6 +1061,7 @@ abstract class FlutterCommand extends Command<void> {
await pub.get( await pub.get(
context: PubContext.getVerifyContext(name), context: PubContext.getVerifyContext(name),
generateSyntheticPackage: project.manifest.generateSyntheticPackage, generateSyntheticPackage: project.manifest.generateSyntheticPackage,
checkUpToDate: true,
); );
await project.regeneratePlatformSpecificTooling(); await project.regeneratePlatformSpecificTooling();
} }
......
...@@ -30,6 +30,269 @@ void main() { ...@@ -30,6 +30,269 @@ void main() {
MockDirectory.findCache = false; MockDirectory.findCache = false;
}); });
testWithoutContext('checkUpToDate skips pub get if the package config is newer than the pubspec '
'and the current framework version is the same as the last version', () async {
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[]);
final BufferLogger logger = BufferLogger.test();
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
fileSystem.file('pubspec.yaml').createSync();
fileSystem.file('pubspec.lock').createSync();
fileSystem.file('.dart_tool/package_config.json').createSync(recursive: true);
fileSystem.file('.dart_tool/version').writeAsStringSync('a');
fileSystem.file('version').writeAsStringSync('a');
final Pub pub = Pub(
fileSystem: fileSystem,
logger: logger,
processManager: processManager,
usage: MockUsage(),
platform: FakePlatform(
environment: const <String, String>{},
),
botDetector: const BotDetectorAlwaysNo(),
);
await pub.get(
context: PubContext.pubGet,
checkUpToDate: true,
);
expect(logger.traceText, contains('Skipping pub get: version match.'));
});
testWithoutContext('checkUpToDate does not skip pub get if the package config is newer than the pubspec '
'but the current framework version is not the same as the last version', () async {
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(command: <String>[
'bin/cache/dart-sdk/bin/pub',
'--verbosity=warning',
'get',
'--no-precompile',
])
]);
final BufferLogger logger = BufferLogger.test();
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
fileSystem.file('pubspec.yaml').createSync();
fileSystem.file('pubspec.lock').createSync();
fileSystem.file('.dart_tool/package_config.json').createSync(recursive: true);
fileSystem.file('.dart_tool/version').writeAsStringSync('a');
fileSystem.file('version').writeAsStringSync('b');
final Pub pub = Pub(
fileSystem: fileSystem,
logger: logger,
processManager: processManager,
usage: MockUsage(),
platform: FakePlatform(
environment: const <String, String>{},
),
botDetector: const BotDetectorAlwaysNo(),
);
await pub.get(
context: PubContext.pubGet,
checkUpToDate: true,
);
expect(processManager.hasRemainingExpectations, false);
expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
});
testWithoutContext('checkUpToDate does not skip pub get if the package config is newer than the pubspec '
'but the current framework version does not exist yet', () async {
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(command: <String>[
'bin/cache/dart-sdk/bin/pub',
'--verbosity=warning',
'get',
'--no-precompile',
])
]);
final BufferLogger logger = BufferLogger.test();
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
fileSystem.file('pubspec.yaml').createSync();
fileSystem.file('pubspec.lock').createSync();
fileSystem.file('.dart_tool/package_config.json').createSync(recursive: true);
fileSystem.file('version').writeAsStringSync('b');
final Pub pub = Pub(
fileSystem: fileSystem,
logger: logger,
processManager: processManager,
usage: MockUsage(),
platform: FakePlatform(
environment: const <String, String>{},
),
botDetector: const BotDetectorAlwaysNo(),
);
await pub.get(
context: PubContext.pubGet,
checkUpToDate: true,
);
expect(processManager.hasRemainingExpectations, false);
expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
});
testWithoutContext('checkUpToDate does not skip pub get if the package config does not exist', () async {
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand(command: const <String>[
'bin/cache/dart-sdk/bin/pub',
'--verbosity=warning',
'get',
'--no-precompile',
], onRun: () {
fileSystem.file('.dart_tool/package_config.json').createSync(recursive: true);
})
]);
final BufferLogger logger = BufferLogger.test();
fileSystem.file('pubspec.yaml').createSync();
fileSystem.file('pubspec.lock').createSync();
fileSystem.file('version').writeAsStringSync('b');
final Pub pub = Pub(
fileSystem: fileSystem,
logger: logger,
processManager: processManager,
usage: MockUsage(),
platform: FakePlatform(
environment: const <String, String>{},
),
botDetector: const BotDetectorAlwaysNo(),
);
await pub.get(
context: PubContext.pubGet,
checkUpToDate: true,
);
expect(processManager.hasRemainingExpectations, false);
expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
});
testWithoutContext('checkUpToDate does not skip pub get if the pubspec.lock does not exist', () async {
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(command: <String>[
'bin/cache/dart-sdk/bin/pub',
'--verbosity=warning',
'get',
'--no-precompile',
]),
]);
final BufferLogger logger = BufferLogger.test();
fileSystem.file('pubspec.yaml').createSync();
fileSystem.file('version').writeAsStringSync('b');
fileSystem.file('.dart_tool/package_config.json').createSync(recursive: true);
fileSystem.file('.dart_tool/version').writeAsStringSync('b');
final Pub pub = Pub(
fileSystem: fileSystem,
logger: logger,
processManager: processManager,
usage: MockUsage(),
platform: FakePlatform(
environment: const <String, String>{},
),
botDetector: const BotDetectorAlwaysNo(),
);
await pub.get(
context: PubContext.pubGet,
checkUpToDate: true,
);
expect(processManager.hasRemainingExpectations, false);
expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
});
testWithoutContext('checkUpToDate does not skip pub get if the package config is older that the pubspec', () async {
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(command: <String>[
'bin/cache/dart-sdk/bin/pub',
'--verbosity=warning',
'get',
'--no-precompile',
])
]);
final BufferLogger logger = BufferLogger.test();
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
fileSystem.file('pubspec.yaml').createSync();
fileSystem.file('pubspec.lock').createSync();
fileSystem.file('.dart_tool/package_config.json')
..createSync(recursive: true)
..setLastModifiedSync(DateTime(1991));
fileSystem.file('version').writeAsStringSync('b');
final Pub pub = Pub(
fileSystem: fileSystem,
logger: logger,
processManager: processManager,
usage: MockUsage(),
platform: FakePlatform(
environment: const <String, String>{},
),
botDetector: const BotDetectorAlwaysNo(),
);
await pub.get(
context: PubContext.pubGet,
checkUpToDate: true,
);
expect(processManager.hasRemainingExpectations, false);
expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
});
testWithoutContext('checkUpToDate does not skip pub get if the pubspec.lock is older that the pubspec', () async {
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(command: <String>[
'bin/cache/dart-sdk/bin/pub',
'--verbosity=warning',
'get',
'--no-precompile',
])
]);
final BufferLogger logger = BufferLogger.test();
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
fileSystem.file('pubspec.yaml').createSync();
fileSystem.file('pubspec.lock')
..createSync()
..setLastModifiedSync(DateTime(1991));
fileSystem.file('.dart_tool/package_config.json')
.createSync(recursive: true);
fileSystem.file('version').writeAsStringSync('b');
fileSystem.file('.dart_tool/version').writeAsStringSync('b');
final Pub pub = Pub(
fileSystem: fileSystem,
logger: logger,
processManager: processManager,
usage: MockUsage(),
platform: FakePlatform(
environment: const <String, String>{},
),
botDetector: const BotDetectorAlwaysNo(),
);
await pub.get(
context: PubContext.pubGet,
checkUpToDate: true,
);
expect(processManager.hasRemainingExpectations, false);
expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
});
testWithoutContext('pub get 69', () async { testWithoutContext('pub get 69', () async {
String error; String error;
...@@ -209,6 +472,7 @@ void main() { ...@@ -209,6 +472,7 @@ void main() {
} }
), ),
); );
fileSystem.file('version').createSync();
fileSystem.file('pubspec.yaml').createSync(); fileSystem.file('pubspec.yaml').createSync();
fileSystem.file('.dart_tool/package_config.json') fileSystem.file('.dart_tool/package_config.json')
..createSync(recursive: true) ..createSync(recursive: true)
...@@ -237,6 +501,7 @@ void main() { ...@@ -237,6 +501,7 @@ void main() {
} }
), ),
); );
fileSystem.file('version').createSync();
fileSystem.file('pubspec.yaml').createSync(); fileSystem.file('pubspec.yaml').createSync();
fileSystem.file('.dart_tool/package_config.json') fileSystem.file('.dart_tool/package_config.json')
..createSync(recursive: true) ..createSync(recursive: true)
...@@ -377,6 +642,7 @@ void main() { ...@@ -377,6 +642,7 @@ void main() {
botDetector: const BotDetectorAlwaysNo() botDetector: const BotDetectorAlwaysNo()
); );
fileSystem.file('version').createSync();
// the good scenario: .packages is old, pub updates the file. // the good scenario: .packages is old, pub updates the file.
fileSystem.file('.dart_tool/package_config.json') fileSystem.file('.dart_tool/package_config.json')
..createSync(recursive: true) ..createSync(recursive: true)
......
...@@ -30,6 +30,7 @@ class ThrowingPub implements Pub { ...@@ -30,6 +30,7 @@ class ThrowingPub implements Pub {
bool skipPubspecYamlCheck = false, bool skipPubspecYamlCheck = false,
bool generateSyntheticPackage = false, bool generateSyntheticPackage = false,
String flutterRootOverride, String flutterRootOverride,
bool checkUpToDate = false,
}) { }) {
throw UnsupportedError('Attempted to invoke pub during test.'); throw UnsupportedError('Attempted to invoke pub during test.');
} }
......
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