Unverified Commit 3246808c authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

[flutter_tools] cache flutter sdk version to disk (#124558)

Fixes https://github.com/flutter/flutter/issues/112833

Most of the actual changes here are in [packages/flutter_tools/lib/src/version.dart](https://github.com/flutter/flutter/pull/124558/files#diff-092e00109d9e1589fbc7c6de750e29a6ae512b2dd44e85d60028953561201605), while the rest is largely just addressing changes to the constructor of `FlutterVersion` which now has different dependencies.

This change makes `FlutterVersion` an interface with two concrete implementations:

1. `_FlutterVersionGit` which is mostly the previous implementation, and
2. `_FlutterVersionFromFile` which will read a new `.version.json` file from the root of the repo

The [`FlutterVersion` constructor](https://github.com/flutter/flutter/pull/124558/files#diff-092e00109d9e1589fbc7c6de750e29a6ae512b2dd44e85d60028953561201605R70) is now a factory that first checks if `.version.json` exists, and if so returns an instance of `_FlutterVersionFromGit` else it returns the fallback `_FlutterVersionGit` which will end up writing `.version.json` so that we don't need to re-calculate the version on the next invocation.

`.version.json` will be deleted in the bash/batch entrypoints any time we need to rebuild he tool (this will usually be because the user did `flutter upgrade` or `flutter channel`, or manually changed the commit with git).
parent 6d2b5ea3
......@@ -128,6 +128,7 @@ GOTO :after_subroutine
:do_snapshot
IF EXIST "%FLUTTER_ROOT%\version" DEL "%FLUTTER_ROOT%\version"
IF EXIST "%FLUTTER_ROOT%\bin\cache\flutter.version.json" DEL "%FLUTTER_ROOT%\bin\cache\flutter.version.json"
ECHO: > "%cache_dir%\.dartignore"
ECHO Building flutter tool... 1>&2
PUSHD "%flutter_tools_dir%"
......
......@@ -123,7 +123,10 @@ function upgrade_flutter () (
# * STAMP_PATH is an empty file, or
# * Contents of STAMP_PATH is not what we are going to compile, or
# * pubspec.yaml last modified after pubspec.lock
if [[ ! -f "$SNAPSHOT_PATH" || ! -s "$STAMP_PATH" || "$(cat "$STAMP_PATH")" != "$compilekey" || "$FLUTTER_TOOLS_DIR/pubspec.yaml" -nt "$FLUTTER_TOOLS_DIR/pubspec.lock" ]]; then
if [[ ! -f "$SNAPSHOT_PATH" || \
! -s "$STAMP_PATH" || \
"$(cat "$STAMP_PATH")" != "$compilekey" || \
"$FLUTTER_TOOLS_DIR/pubspec.yaml" -nt "$FLUTTER_TOOLS_DIR/pubspec.lock" ]]; then
# Waits for the update lock to be acquired. Placing this check inside the
# conditional allows the majority of flutter/dart installations to bypass
# the lock entirely, but as a result this required a second verification that
......@@ -137,6 +140,7 @@ function upgrade_flutter () (
# Fetch Dart...
rm -f "$FLUTTER_ROOT/version"
rm -f "$FLUTTER_ROOT/bin/cache/flutter.version.json"
touch "$FLUTTER_ROOT/bin/cache/.dartignore"
"$FLUTTER_ROOT/bin/internal/update_dart_sdk.sh"
......
......@@ -33,7 +33,6 @@ class DoctorCommand extends FlutterCommand {
@override
Future<FlutterCommandResult> runCommand() async {
globals.flutterVersion.fetchTagsAndUpdate();
if (argResults?.wasParsed('check-for-remote-artifacts') ?? false) {
final String engineRevision = stringArg('check-for-remote-artifacts')!;
if (engineRevision.startsWith(RegExp(r'[a-f0-9]{1,40}'))) {
......
......@@ -92,7 +92,10 @@ class DowngradeCommand extends FlutterCommand {
String workingDirectory = Cache.flutterRoot!;
if (argResults!.wasParsed('working-directory')) {
workingDirectory = stringArg('working-directory')!;
_flutterVersion = FlutterVersion(workingDirectory: workingDirectory);
_flutterVersion = FlutterVersion(
fs: _fileSystem!,
flutterRoot: workingDirectory,
);
}
final String currentChannel = _flutterVersion!.channel;
......
......@@ -80,7 +80,7 @@ class UpgradeCommand extends FlutterCommand {
gitTagVersion: GitTagVersion.determine(globals.processUtils, globals.platform),
flutterVersion: stringArg('working-directory') == null
? globals.flutterVersion
: FlutterVersion(workingDirectory: _commandRunner.workingDirectory),
: FlutterVersion(flutterRoot: _commandRunner.workingDirectory!, fs: globals.fs),
verifyOnly: boolArg('verify-only'),
);
}
......@@ -297,7 +297,11 @@ class UpgradeCommandRunner {
'for instructions.'
);
}
return FlutterVersion(workingDirectory: workingDirectory, frameworkRevision: revision);
return FlutterVersion.fromRevision(
flutterRoot: workingDirectory!,
frameworkRevision: revision,
fs: globals.fs,
);
}
/// Attempts a hard reset to the given revision.
......
......@@ -226,7 +226,10 @@ Future<T> runInContext<T>(
config: globals.config,
platform: globals.platform,
),
FlutterVersion: () => FlutterVersion(),
FlutterVersion: () => FlutterVersion(
fs: globals.fs,
flutterRoot: Cache.flutterRoot!,
),
FuchsiaArtifacts: () => FuchsiaArtifacts.find(),
FuchsiaDeviceTools: () => FuchsiaDeviceTools(),
FuchsiaSdk: () => FuchsiaSdk(),
......
......@@ -123,7 +123,7 @@ class _DefaultDoctorValidatorsProvider implements DoctorValidatorsProvider {
FlutterValidator(
fileSystem: globals.fs,
platform: globals.platform,
flutterVersion: () => globals.flutterVersion,
flutterVersion: () => globals.flutterVersion.fetchTagsAndGetVersion(clock: globals.systemClock),
devToolsVersion: () => globals.cache.devToolsVersion,
processManager: globals.processManager,
userMessages: userMessages,
......
......@@ -136,7 +136,10 @@ class VariableDumpMachineProjectValidator extends MachineProjectValidator {
));
// FlutterVersion
final FlutterVersion version = FlutterVersion(workingDirectory: project.directory.absolute.path);
final FlutterVersion version = FlutterVersion(
flutterRoot: Cache.flutterRoot!,
fs: fileSystem,
);
result.add(ProjectValidatorResult(
name: 'FlutterVersion.frameworkRevision',
value: _toJsonValue(version.frameworkRevision),
......
......@@ -18,6 +18,7 @@ import '../cache.dart';
import '../convert.dart';
import '../globals.dart' as globals;
import '../tester/flutter_tester.dart';
import '../version.dart';
import '../web/web_device.dart';
/// Common flutter command line options.
......@@ -318,14 +319,16 @@ class FlutterCommandRunner extends CommandRunner<void> {
if ((topLevelResults[FlutterGlobalOptions.kVersionFlag] as bool?) ?? false) {
globals.flutterUsage.sendCommand(FlutterGlobalOptions.kVersionFlag);
globals.flutterVersion.fetchTagsAndUpdate();
String status;
final FlutterVersion version = globals.flutterVersion.fetchTagsAndGetVersion(
clock: globals.systemClock,
);
final String status;
if (machineFlag) {
final Map<String, Object> jsonOut = globals.flutterVersion.toJson();
final Map<String, Object> jsonOut = version.toJson();
jsonOut['flutterRoot'] = Cache.flutterRoot!;
status = const JsonEncoder.withIndent(' ').convert(jsonOut);
} else {
status = globals.flutterVersion.toString();
status = version.toString();
}
globals.printStatus(status);
return;
......
This diff is collapsed.
......@@ -13,8 +13,10 @@ import 'base/context.dart';
import 'base/io.dart' as io;
import 'base/logger.dart';
import 'base/utils.dart';
import 'cache.dart';
import 'convert.dart';
import 'device.dart';
import 'globals.dart' as globals;
import 'ios/xcodeproj.dart';
import 'project.dart';
import 'version.dart';
......@@ -244,7 +246,10 @@ Future<vm_service.VmService> setUpVmService({
}
vmService.registerServiceCallback(kFlutterVersionServiceName, (Map<String, Object?> params) async {
final FlutterVersion version = context.get<FlutterVersion>() ?? FlutterVersion();
final FlutterVersion version = context.get<FlutterVersion>() ?? FlutterVersion(
fs: globals.fs,
flutterRoot: Cache.flutterRoot!,
);
final Map<String, Object> versionJson = version.toJson();
versionJson['frameworkRevisionShort'] = version.frameworkRevisionShort;
versionJson['engineRevisionShort'] = version.engineRevisionShort;
......
......@@ -4,7 +4,6 @@
import 'dart:async';
import 'package:args/command_runner.dart';
import 'package:fake_async/fake_async.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_studio_validator.dart';
......@@ -16,7 +15,6 @@ import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/base/user_messages.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/doctor.dart';
import 'package:flutter_tools/src/custom_devices/custom_device_workflow.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/doctor.dart';
......@@ -32,17 +30,16 @@ import 'package:test/fake.dart';
import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/fakes.dart';
import '../../src/test_flutter_command_runner.dart';
void main() {
late FakeFlutterVersion flutterVersion;
late BufferLogger logger;
late FakeProcessManager fakeProcessManager;
late MemoryFileSystem fs;
setUp(() {
flutterVersion = FakeFlutterVersion();
logger = BufferLogger.test();
fakeProcessManager = FakeProcessManager.empty();
fs = MemoryFileSystem.test();
});
testWithoutContext('ValidationMessage equality and hashCode includes contextUrl', () {
......@@ -761,27 +758,55 @@ void main() {
contains(isA<CustomDeviceWorkflow>()),
);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
FileSystem: () => fs,
ProcessManager: () => fakeProcessManager,
});
testUsingContext('Fetches tags to get the right version', () async {
Cache.disableLocking();
final DoctorCommand doctorCommand = DoctorCommand();
final CommandRunner<void> commandRunner = createTestCommandRunner(doctorCommand);
group('FlutterValidator', () {
late FakeFlutterVersion initialVersion;
late FakeFlutterVersion secondVersion;
late TestFeatureFlags featureFlags;
await commandRunner.run(<String>['doctor']);
expect(flutterVersion.didFetchTagsAndUpdate, true);
Cache.enableLocking();
}, overrides: <Type, Generator>{
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => MemoryFileSystem.test(),
FlutterVersion: () => flutterVersion,
Doctor: () => NoOpDoctor(),
}, initializeFlutterRoot: false);
setUp(() {
secondVersion = FakeFlutterVersion(frameworkRevisionShort: '222');
initialVersion = FakeFlutterVersion(
frameworkRevisionShort: '111',
nextFlutterVersion: secondVersion,
);
featureFlags = TestFeatureFlags();
});
testUsingContext('FlutterValidator fetches tags and gets fresh version', () async {
final Directory devtoolsDir = fs.directory('/path/to/flutter/bin/cache/dart-sdk/bin/resources/devtools')
..createSync(recursive: true);
fs.directory('/path/to/flutter/bin/cache/artifacts').createSync(recursive: true);
devtoolsDir.childFile('version.json').writeAsStringSync('{"version": "123"}');
fakeProcessManager.addCommands(const <FakeCommand>[
FakeCommand(command: <String>['which', 'java']),
]);
final List<DoctorValidator> validators = DoctorValidatorsProvider.test(
featureFlags: featureFlags,
platform: FakePlatform(),
).validators;
final FlutterValidator flutterValidator = validators.whereType<FlutterValidator>().first;
final ValidationResult result = await flutterValidator.validate();
expect(
result.messages.map((ValidationMessage msg) => msg.message),
contains(contains('Framework revision 222')),
);
}, overrides: <Type, Generator>{
Cache: () => Cache.test(
rootOverride: fs.directory('/path/to/flutter'),
fileSystem: fs,
processManager: fakeProcessManager,
),
FileSystem: () => fs,
FlutterVersion: () => initialVersion,
Platform: () => FakePlatform(),
ProcessManager: () => fakeProcessManager,
TestFeatureFlags: () => featureFlags,
});
});
testUsingContext('If android workflow is disabled, AndroidStudio validator is not included', () {
final DoctorValidatorsProvider provider = DoctorValidatorsProvider.test(
featureFlags: TestFeatureFlags(isAndroidEnabled: false),
......@@ -826,6 +851,7 @@ class NoOpDoctor implements Doctor {
bool showPii = true,
List<ValidatorTask>? startedValidatorTasks,
bool sendEvent = true,
FlutterVersion? version,
}) async => true;
@override
......
......@@ -37,7 +37,8 @@ void main() {
setUp(() {
fakeCommandRunner = FakeUpgradeCommandRunner();
realCommandRunner = UpgradeCommandRunner();
realCommandRunner = UpgradeCommandRunner()
..workingDirectory = Cache.flutterRoot;
processManager = FakeProcessManager.empty();
fakeCommandRunner.willHaveUncommittedChanges = false;
fakePlatform = FakePlatform()..environment = Map<String, String>.unmodifiable(<String, String>{
......
......@@ -41,11 +41,14 @@ void main() {
group('analytics', () {
late Directory tempDir;
late Config testConfig;
late FileSystem fs;
const String flutterRoot = '/path/to/flutter';
setUp(() {
Cache.flutterRoot = '../..';
Cache.flutterRoot = flutterRoot;
tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_tools_analytics_test.');
testConfig = Config.test();
fs = MemoryFileSystem.test();
});
tearDown(() {
......@@ -77,7 +80,7 @@ void main() {
expect(count, 0);
}, overrides: <Type, Generator>{
FlutterVersion: () => FlutterVersion(),
FlutterVersion: () => FakeFlutterVersion(),
Usage: () => Usage(
configDirOverride: tempDir.path,
logFile: tempDir.childFile('analytics.log').path,
......@@ -101,7 +104,7 @@ void main() {
expect(count, 0);
}, overrides: <Type, Generator>{
FlutterVersion: () => FlutterVersion(),
FlutterVersion: () => FakeFlutterVersion(),
Usage: () => Usage(
configDirOverride: tempDir.path,
logFile: tempDir.childFile('analytics.log').path,
......@@ -118,12 +121,12 @@ void main() {
expect(globals.fs.file('test').readAsStringSync(), contains('$featuresKey: enable-web'));
}, overrides: <Type, Generator>{
FlutterVersion: () => FlutterVersion(),
FlutterVersion: () => FakeFlutterVersion(),
Config: () => testConfig,
Platform: () => FakePlatform(environment: <String, String>{
'FLUTTER_ANALYTICS_LOG_FILE': 'test',
}),
FileSystem: () => MemoryFileSystem.test(),
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
......@@ -141,12 +144,12 @@ void main() {
contains('$featuresKey: enable-web,enable-linux-desktop,enable-macos-desktop'),
);
}, overrides: <Type, Generator>{
FlutterVersion: () => FlutterVersion(),
FlutterVersion: () => FakeFlutterVersion(),
Config: () => testConfig,
Platform: () => FakePlatform(environment: <String, String>{
'FLUTTER_ANALYTICS_LOG_FILE': 'test',
}),
FileSystem: () => MemoryFileSystem.test(),
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
});
......@@ -384,6 +387,7 @@ class FakeDoctor extends Fake implements Doctor {
bool showPii = true,
List<ValidatorTask>? startedValidatorTasks,
bool sendEvent = true,
FlutterVersion? version,
}) async {
return diagnoseSucceeds;
}
......
......@@ -4,12 +4,13 @@
import 'dart:convert';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/version.dart';
import 'package:test/fake.dart';
......@@ -18,7 +19,7 @@ import '../src/context.dart';
import '../src/fake_process_manager.dart';
import '../src/fakes.dart' show FakeFlutterVersion;
final SystemClock _testClock = SystemClock.fixed(DateTime(2015));
final SystemClock _testClock = SystemClock.fixed(DateTime.utc(2015));
final DateTime _stampUpToDate = _testClock.ago(VersionFreshnessValidator.checkAgeConsideredUpToDate ~/ 2);
final DateTime _stampOutOfDate = _testClock.ago(VersionFreshnessValidator.checkAgeConsideredUpToDate * 2);
......@@ -49,7 +50,11 @@ void main() {
}
group('$FlutterVersion for $channel', () {
late FileSystem fs;
const String flutterRoot = '/path/to/flutter';
setUpAll(() {
fs = MemoryFileSystem.test();
Cache.disableLocking();
VersionFreshnessValidator.timeToPauseToLetUserReadTheMessage = Duration.zero;
});
......@@ -101,7 +106,7 @@ void main() {
),
]);
final FlutterVersion flutterVersion = globals.flutterVersion;
final FlutterVersion flutterVersion = FlutterVersion(clock: _testClock, fs: fs, flutterRoot: flutterRoot);
await flutterVersion.checkFlutterVersionFreshness();
expect(flutterVersion.channel, channel);
expect(flutterVersion.repositoryUrl, flutterUpstreamUrl);
......@@ -124,7 +129,6 @@ void main() {
expect(testLogger.statusText, isEmpty);
expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
FlutterVersion: () => FlutterVersion(clock: _testClock),
ProcessManager: () => processManager,
Cache: () => cache,
});
......@@ -419,15 +423,197 @@ void main() {
),
]);
final FlutterVersion flutterVersion = globals.flutterVersion;
final MemoryFileSystem fs = MemoryFileSystem.test();
final FlutterVersion flutterVersion = FlutterVersion(
clock: _testClock,
fs: fs,
flutterRoot: '/path/to/flutter',
);
expect(flutterVersion.channel, '[user-branch]');
expect(flutterVersion.getVersionString(), 'feature-branch/1234abcd');
expect(flutterVersion.getBranchName(), 'feature-branch');
expect(flutterVersion.getVersionString(redactUnknownBranches: true), '[user-branch]/1234abcd');
expect(flutterVersion.getBranchName(redactUnknownBranches: true), '[user-branch]');
expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Cache: () => cache,
});
testUsingContext('ensureVersionFile() writes version information to disk', () async {
processManager.addCommands(<FakeCommand>[
const FakeCommand(
command: <String>['git', '-c', 'log.showSignature=false', 'log', '-n', '1', '--pretty=format:%H'],
stdout: '1234abcd',
),
const FakeCommand(
command: <String>['git', 'tag', '--points-at', '1234abcd'],
),
const FakeCommand(
command: <String>['git', 'describe', '--match', '*.*.*', '--long', '--tags', '1234abcd'],
stdout: '0.1.2-3-1234abcd',
),
const FakeCommand(
command: <String>['git', 'symbolic-ref', '--short', 'HEAD'],
stdout: 'feature-branch',
),
const FakeCommand(
command: <String>['git', 'rev-parse', '--abbrev-ref', '--symbolic', '@{upstream}'],
),
FakeCommand(
command: const <String>[
'git',
'-c',
'log.showSignature=false',
'log',
'HEAD',
'-n',
'1',
'--pretty=format:%ad',
'--date=iso',
],
stdout: _testClock.ago(VersionFreshnessValidator.versionAgeConsideredUpToDate('stable') ~/ 2).toString(),
),
]);
final MemoryFileSystem fs = MemoryFileSystem.test();
final Directory flutterRoot = fs.directory('/path/to/flutter');
flutterRoot.childDirectory('bin').childDirectory('cache').createSync(recursive: true);
final FlutterVersion flutterVersion = FlutterVersion(
clock: _testClock,
fs: fs,
flutterRoot: flutterRoot.path,
);
final File versionFile = fs.file('/path/to/flutter/bin/cache/flutter.version.json');
expect(versionFile.existsSync(), isFalse);
flutterVersion.ensureVersionFile();
expect(versionFile.existsSync(), isTrue);
expect(versionFile.readAsStringSync(), '''
{
"frameworkVersion": "0.0.0-unknown",
"channel": "[user-branch]",
"repositoryUrl": "unknown source",
"frameworkRevision": "1234abcd",
"frameworkCommitDate": "2014-10-02 00:00:00.000Z",
"engineRevision": "abcdefg",
"dartSdkVersion": "2.12.0",
"devToolsVersion": "2.8.0",
"flutterVersion": "0.0.0-unknown"
}''');
expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Cache: () => cache,
});
testUsingContext('version does not call git if a .version.json file exists', () async {
final MemoryFileSystem fs = MemoryFileSystem.test();
final Directory flutterRoot = fs.directory('/path/to/flutter');
final Directory cacheDir = flutterRoot
.childDirectory('bin')
.childDirectory('cache')
..createSync(recursive: true);
const String devToolsVersion = '0000000';
const Map<String, Object> versionJson = <String, Object>{
'channel': 'stable',
'frameworkVersion': '1.2.3',
'repositoryUrl': 'https://github.com/flutter/flutter.git',
'frameworkRevision': '1234abcd',
'frameworkCommitDate': '2023-04-28 12:34:56 -0400',
'engineRevision': 'deadbeef',
'dartSdkVersion': 'deadbeef2',
'devToolsVersion': devToolsVersion,
'flutterVersion': 'foo',
};
cacheDir.childFile('flutter.version.json').writeAsStringSync(
jsonEncode(versionJson),
);
final FlutterVersion flutterVersion = FlutterVersion(
clock: _testClock,
fs: fs,
flutterRoot: flutterRoot.path,
);
expect(flutterVersion.channel, 'stable');
expect(flutterVersion.getVersionString(), 'stable/1.2.3');
expect(flutterVersion.getBranchName(), 'stable');
expect(flutterVersion.dartSdkVersion, 'deadbeef2');
expect(flutterVersion.devToolsVersion, devToolsVersion);
expect(flutterVersion.engineRevision, 'deadbeef');
expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Cache: () => cache,
});
testUsingContext('FlutterVersion() falls back to git if .version.json is malformed', () async {
final MemoryFileSystem fs = MemoryFileSystem.test();
final Directory flutterRoot = fs.directory(fs.path.join('path', 'to', 'flutter'));
final Directory cacheDir = flutterRoot
.childDirectory('bin')
.childDirectory('cache')
..createSync(recursive: true);
final File legacyVersionFile = flutterRoot.childFile('version');
final File versionFile = cacheDir.childFile('flutter.version.json')..writeAsStringSync(
'{',
);
processManager.addCommands(<FakeCommand>[
const FakeCommand(
command: <String>['git', '-c', 'log.showSignature=false', 'log', '-n', '1', '--pretty=format:%H'],
stdout: '1234abcd',
),
const FakeCommand(
command: <String>['git', 'tag', '--points-at', '1234abcd'],
),
const FakeCommand(
command: <String>['git', 'describe', '--match', '*.*.*', '--long', '--tags', '1234abcd'],
stdout: '0.1.2-3-1234abcd',
),
const FakeCommand(
command: <String>['git', 'symbolic-ref', '--short', 'HEAD'],
stdout: 'feature-branch',
),
const FakeCommand(
command: <String>['git', 'rev-parse', '--abbrev-ref', '--symbolic', '@{upstream}'],
stdout: 'feature-branch',
),
FakeCommand(
command: const <String>[
'git',
'-c',
'log.showSignature=false',
'log',
'HEAD',
'-n',
'1',
'--pretty=format:%ad',
'--date=iso',
],
stdout: _testClock.ago(VersionFreshnessValidator.versionAgeConsideredUpToDate('stable') ~/ 2).toString(),
),
]);
// version file exists in a malformed state
expect(versionFile.existsSync(), isTrue);
final FlutterVersion flutterVersion = FlutterVersion(
clock: _testClock,
fs: fs,
flutterRoot: flutterRoot.path,
);
// version file was deleted because it couldn't be parsed
expect(versionFile.existsSync(), isFalse);
expect(legacyVersionFile.existsSync(), isFalse);
// version file was written to disk
flutterVersion.ensureVersionFile();
expect(processManager, hasNoRemainingExpectations);
expect(versionFile.existsSync(), isTrue);
expect(legacyVersionFile.existsSync(), isTrue);
}, overrides: <Type, Generator>{
FlutterVersion: () => FlutterVersion(clock: _testClock),
ProcessManager: () => processManager,
Cache: () => cache,
});
......
......@@ -158,7 +158,6 @@ void main() {
expect(decoded['FlutterProject.isModule'], false);
expect(decoded['FlutterProject.isPlugin'], false);
expect(decoded['FlutterProject.manifest.appname'], 'test_project');
expect(decoded['FlutterVersion.frameworkRevision'], '');
expect(decoded['Platform.isAndroid'], false);
expect(decoded['Platform.isIOS'], false);
......
......@@ -43,8 +43,6 @@ void main() {
final Directory testDirectory = parentDirectory.childDirectory('flutter');
testDirectory.createSync(recursive: true);
int exitCode = 0;
// Enable longpaths for windows integration test.
await processManager.run(<String>[
'git', 'config', '--system', 'core.longpaths', 'true',
......
......@@ -24,14 +24,18 @@ void main() {
);
exampleAppDir = tempDir.childDirectory('bbb').childDirectory('example');
processManager.runSync(<String>[
flutterBin,
...getLocalEngineArguments(),
'create',
'--template=plugin',
'--platforms=android',
'bbb',
], workingDirectory: tempDir.path);
processManager.runSync(
<String>[
flutterBin,
...getLocalEngineArguments(),
'create',
'--template=plugin',
'--platforms=android',
'bbb',
'-v',
],
workingDirectory: tempDir.path,
);
});
tearDown(() async {
......@@ -48,14 +52,17 @@ void main() {
// Ensure file is gone prior to configOnly running.
await gradleFile.delete();
final ProcessResult result = processManager.runSync(<String>[
flutterBin,
...getLocalEngineArguments(),
'build',
'apk',
'--target-platform=android-arm',
'--config-only',
], workingDirectory: exampleAppDir.path);
final ProcessResult result = processManager.runSync(
<String>[
flutterBin,
...getLocalEngineArguments(),
'build',
'apk',
'--target-platform=android-arm',
'--config-only',
],
workingDirectory: exampleAppDir.path,
);
expect(gradleFile, exists);
expect(result.stdout, contains(RegExp(r'Config complete')));
......
......@@ -13,6 +13,7 @@ import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/base/version.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/convert.dart';
......@@ -337,6 +338,8 @@ class FakeFlutterVersion implements FlutterVersion {
this.frameworkAge = '0 hours ago',
this.frameworkCommitDate = '12/01/01',
this.gitTagVersion = const GitTagVersion.unknown(),
this.flutterRoot = '/path/to/flutter',
this.nextFlutterVersion,
});
final String branch;
......@@ -344,6 +347,17 @@ class FakeFlutterVersion implements FlutterVersion {
bool get didFetchTagsAndUpdate => _didFetchTagsAndUpdate;
bool _didFetchTagsAndUpdate = false;
/// Will be returned by [fetchTagsAndGetVersion] if not null.
final FlutterVersion? nextFlutterVersion;
@override
FlutterVersion fetchTagsAndGetVersion({
SystemClock clock = const SystemClock(),
}) {
_didFetchTagsAndUpdate = true;
return nextFlutterVersion ?? this;
}
bool get didCheckFlutterVersionFreshness => _didCheckFlutterVersionFreshness;
bool _didCheckFlutterVersionFreshness = false;
......@@ -355,6 +369,9 @@ class FakeFlutterVersion implements FlutterVersion {
return kUserBranch;
}
@override
final String flutterRoot;
@override
final String devToolsVersion;
......@@ -385,16 +402,11 @@ class FakeFlutterVersion implements FlutterVersion {
@override
final String frameworkCommitDate;
@override
String get frameworkDate => frameworkCommitDate;
@override
final GitTagVersion gitTagVersion;
@override
void fetchTagsAndUpdate() {
_didFetchTagsAndUpdate = true;
}
FileSystem get fs => throw UnimplementedError('FakeFlutterVersion.fs is not implemented');
@override
Future<void> checkFlutterVersionFreshness() async {
......
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