diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart index 97fe42d429..bfdb74c5b4 100644 --- a/packages/flutter_tools/lib/src/cache.dart +++ b/packages/flutter_tools/lib/src/cache.dart @@ -51,6 +51,9 @@ class Cache { _artifacts.add(GradleWrapper(this)); _artifacts.add(FlutterWebSdk(this)); _artifacts.add(FlutterSdk(this)); + _artifacts.add(WindowsEngineArtifacts(this)); + _artifacts.add(MacOSEngineArtifacts(this)); + _artifacts.add(LinuxEngineArtifacts(this)); } else { _artifacts.addAll(artifacts); } @@ -535,11 +538,14 @@ abstract class EngineCachedArtifact extends CachedArtifact { _makeFilesExecutable(dir); - final File frameworkZip = fs.file(fs.path.join(dir.path, 'Flutter.framework.zip')); - if (frameworkZip.existsSync()) { - final Directory framework = fs.directory(fs.path.join(dir.path, 'Flutter.framework')); - framework.createSync(); - os.unzip(frameworkZip, framework); + const List frameworkNames = ['Flutter', 'FlutterMacOS']; + for (String frameworkName in frameworkNames) { + final File frameworkZip = fs.file(fs.path.join(dir.path, '$frameworkName.framework.zip')); + if (frameworkZip.existsSync()) { + final Directory framework = fs.directory(fs.path.join(dir.path, '$frameworkName.framework')); + framework.createSync(); + os.unzip(frameworkZip, framework); + } } } @@ -630,6 +636,72 @@ class FlutterSdk extends EngineCachedArtifact { List getLicenseDirs() => const []; } +class MacOSEngineArtifacts extends EngineCachedArtifact { + MacOSEngineArtifacts(Cache cache) : super( + 'macos-sdk', + cache, + const { DevelopmentArtifact.macOS }, + ); + + @override + List getPackageDirs() => const []; + + @override + List> getBinaryDirs() { + if (platform.isMacOS) { + return _macOSDesktopBinaryDirs; + } + return const >[]; + } + + @override + List getLicenseDirs() => const []; +} + +class WindowsEngineArtifacts extends EngineCachedArtifact { + WindowsEngineArtifacts(Cache cache) : super( + 'windows-sdk', + cache, + const { DevelopmentArtifact.windows }, + ); + + @override + List getPackageDirs() => const []; + + @override + List> getBinaryDirs() { + if (platform.isWindows) { + return _windowsDesktopBinaryDirs; + } + return const >[]; + } + + @override + List getLicenseDirs() => const []; +} + +class LinuxEngineArtifacts extends EngineCachedArtifact { + LinuxEngineArtifacts(Cache cache) : super( + 'linux-sdk', + cache, + const { DevelopmentArtifact.linux }, + ); + + @override + List getPackageDirs() => const []; + + @override + List> getBinaryDirs() { + if (platform.isLinux) { + return _linuxDesktopBinaryDirs; + } + return const >[]; + } + + @override + List getLicenseDirs() => const []; +} + class AndroidEngineArtifacts extends EngineCachedArtifact { AndroidEngineArtifacts(Cache cache) : super( 'android-sdk', @@ -797,6 +869,20 @@ void _ensureExists(Directory directory) { } } +const List> _windowsDesktopBinaryDirs = >[ + ['windows-x64', 'windows-x64/windows-x64-flutter.zip'], + ['windows-x64', 'windows-x64/flutter-cpp-client-wrapper.zip'], +]; + +const List> _linuxDesktopBinaryDirs = >[ + ['linux-x64', 'linux-x64/linux-x64-flutter.zip'], + ['linux-x64', 'linux-x64/flutter-cpp-client-wrapper.zip'], +]; + +const List> _macOSDesktopBinaryDirs = >[ + ['darwin-x64', 'darwin-x64/FlutterMacOS.framework.zip'], +]; + const List> _osxBinaryDirs = >[ ['android-arm-profile/darwin-x64', 'android-arm-profile/darwin-x64.zip'], ['android-arm-release/darwin-x64', 'android-arm-release/darwin-x64.zip'], diff --git a/packages/flutter_tools/lib/src/commands/precache.dart b/packages/flutter_tools/lib/src/commands/precache.dart index 858d338353..9c39c00db3 100644 --- a/packages/flutter_tools/lib/src/commands/precache.dart +++ b/packages/flutter_tools/lib/src/commands/precache.dart @@ -7,6 +7,7 @@ import 'dart:async'; import '../cache.dart'; import '../globals.dart'; import '../runner/flutter_command.dart'; +import '../version.dart'; class PrecacheCommand extends FlutterCommand { PrecacheCommand() { @@ -18,6 +19,12 @@ class PrecacheCommand extends FlutterCommand { help: 'Precache artifacts for iOS developemnt'); argParser.addFlag('web', negatable: true, defaultsTo: false, help: 'Precache artifacts for web development'); + argParser.addFlag('linux', negatable: true, defaultsTo: false, + help: 'Precache artifacts for linux desktop development'); + argParser.addFlag('windows', negatable: true, defaultsTo: false, + help: 'Precache artifacts for windows desktop development'); + argParser.addFlag('macos', negatable: true, defaultsTo: false, + help: 'Precache artifacts for macOS desktop development'); } @override @@ -41,8 +48,19 @@ class PrecacheCommand extends FlutterCommand { if (argResults['ios']) { requiredArtifacts.add(DevelopmentArtifact.iOS); } - if (argResults['web']) { - requiredArtifacts.add(DevelopmentArtifact.web); + if (!FlutterVersion.instance.isStable) { + if (argResults['web']) { + requiredArtifacts.add(DevelopmentArtifact.web); + } + if (argResults['linux']) { + requiredArtifacts.add(DevelopmentArtifact.linux); + } + if (argResults['windows']) { + requiredArtifacts.add(DevelopmentArtifact.windows); + } + if (argResults['macos']) { + requiredArtifacts.add(DevelopmentArtifact.macOS); + } } if (cache.isUpToDate()) { diff --git a/packages/flutter_tools/test/commands/precache_test.dart b/packages/flutter_tools/test/commands/precache_test.dart new file mode 100644 index 0000000000..090df1b6c6 --- /dev/null +++ b/packages/flutter_tools/test/commands/precache_test.dart @@ -0,0 +1,69 @@ +// Copyright 2019 The Chromium 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:flutter_tools/src/cache.dart'; +import 'package:flutter_tools/src/commands/precache.dart'; +import 'package:flutter_tools/src/runner/flutter_command.dart'; +import 'package:flutter_tools/src/version.dart'; +import 'package:mockito/mockito.dart'; + +import '../src/common.dart'; +import '../src/context.dart'; +import '../src/mocks.dart'; + +void main() { + group('precache', () { + final MockCache cache = MockCache(); + Set artifacts; + + when(cache.isUpToDate()).thenReturn(false); + when(cache.updateAll(any)).thenAnswer((Invocation invocation) { + artifacts = invocation.positionalArguments.first; + return Future.value(null); + }); + + testUsingContext('Adds artifact flags to requested artifacts', () async { + final PrecacheCommand command = PrecacheCommand(); + applyMocksToCommand(command); + await createTestCommandRunner(command).run( + const ['precache', '--ios', '--android', '--web', '--macos', '--linux', '--windows'] + ); + expect(artifacts, unorderedEquals({ + DevelopmentArtifact.universal, + DevelopmentArtifact.iOS, + DevelopmentArtifact.android, + DevelopmentArtifact.web, + DevelopmentArtifact.macOS, + DevelopmentArtifact.linux, + DevelopmentArtifact.windows, + })); + }, overrides: { + Cache: () => cache, + }); + + final MockFlutterVersion flutterVersion = MockFlutterVersion(); + when(flutterVersion.isStable).thenReturn(true); + + testUsingContext('Adds artifact flags to requested artifacts on stable', () async { + // Release lock between test cases. + Cache.releaseLockEarly(); + final PrecacheCommand command = PrecacheCommand(); + applyMocksToCommand(command); + await createTestCommandRunner(command).run( + const ['precache', '--ios', '--android', '--web', '--macos', '--linux', '--windows'] + ); + expect(artifacts, unorderedEquals({ + DevelopmentArtifact.universal, + DevelopmentArtifact.iOS, + DevelopmentArtifact.android, + })); + }, overrides: { + Cache: () => cache, + FlutterVersion: () => flutterVersion, + }); + }); +} + +class MockFlutterVersion extends Mock implements FlutterVersion {} +class MockCache extends Mock implements Cache {}