Revert "Move plugin injection to just after pub get (#14560)" (#14734)
This reverts commit b3e4976ca20dc878bd8a484b877b66351bed86e4.
diff --git a/dev/devicelab/bin/tasks/plugin_test.dart b/dev/devicelab/bin/tasks/plugin_test.dart
deleted file mode 100644
index 3217961..0000000
--- a/dev/devicelab/bin/tasks/plugin_test.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2018 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 'dart:async';
-
-import 'package:flutter_devicelab/tasks/plugin_tests.dart';
-import 'package:flutter_devicelab/framework/framework.dart';
-
-Future<Null> main() async {
- await task(new PluginTest('apk'));
-}
diff --git a/dev/devicelab/bin/tasks/plugin_test_ios.dart b/dev/devicelab/bin/tasks/plugin_test_ios.dart
deleted file mode 100644
index 492e7d6..0000000
--- a/dev/devicelab/bin/tasks/plugin_test_ios.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2018 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 'dart:async';
-
-import 'package:flutter_devicelab/tasks/plugin_tests.dart';
-import 'package:flutter_devicelab/framework/framework.dart';
-
-Future<Null> main() async {
- await task(new PluginTest('ios'));
-}
diff --git a/dev/devicelab/bin/tasks/plugin_test_win.dart b/dev/devicelab/bin/tasks/plugin_test_win.dart
deleted file mode 100644
index 3217961..0000000
--- a/dev/devicelab/bin/tasks/plugin_test_win.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2018 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 'dart:async';
-
-import 'package:flutter_devicelab/tasks/plugin_tests.dart';
-import 'package:flutter_devicelab/framework/framework.dart';
-
-Future<Null> main() async {
- await task(new PluginTest('apk'));
-}
diff --git a/dev/devicelab/lib/tasks/plugin_tests.dart b/dev/devicelab/lib/tasks/plugin_tests.dart
deleted file mode 100644
index 1e06a4f..0000000
--- a/dev/devicelab/lib/tasks/plugin_tests.dart
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2018 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 'dart:async';
-import 'dart:io';
-
-import 'package:path/path.dart' as path;
-import 'package:flutter_devicelab/framework/framework.dart';
-import 'package:flutter_devicelab/framework/utils.dart';
-
-/// Defines task that creates new Flutter project, adds a plugin, and then
-/// builds the specified [buildTarget].
-class PluginTest {
- final String buildTarget;
-
- PluginTest(this.buildTarget);
-
- Future<TaskResult> call() async {
- section('Create Flutter project');
- final Directory tmp = await Directory.systemTemp.createTemp('plugin');
- final FlutterProject project = await FlutterProject.create(tmp, 'hello');
- try {
- section('Add plugin');
- await project.addPlugin('path_provider');
-
- section('Build');
- await project.build(buildTarget);
-
- return new TaskResult.success(null);
- } catch (e) {
- return new TaskResult.failure(e.toString());
- } finally {
- await project.delete();
- }
- }
-}
-
-class FlutterProject {
- FlutterProject(this.parent, this.name);
-
- final Directory parent;
- final String name;
-
- static Future<FlutterProject> create(Directory directory, String name) async {
- await inDirectory(directory, () async {
- await flutter('create', options: <String>[name]);
- });
- return new FlutterProject(directory, name);
- }
-
- String get rootPath => path.join(parent.path, name);
-
- Future<Null> addPlugin(String plugin) async {
- final File pubspec = new File(path.join(rootPath, 'pubspec.yaml'));
- String content = await pubspec.readAsString();
- content = content.replaceFirst(
- '\ndependencies:\n',
- '\ndependencies:\n $plugin:\n',
- );
- await pubspec.writeAsString(content, flush: true);
- }
-
- Future<Null> build(String target) async {
- await inDirectory(new Directory(rootPath), () async {
- await flutter('build', options: <String>[target]);
- });
- }
-
- Future<Null> delete() async {
- await parent.delete(recursive: true);
- }
-}
diff --git a/dev/devicelab/manifest.yaml b/dev/devicelab/manifest.yaml
index 27a0bfc..63b3d1f 100644
--- a/dev/devicelab/manifest.yaml
+++ b/dev/devicelab/manifest.yaml
@@ -237,13 +237,6 @@
stage: devicelab
required_agent_capabilities: ["linux/android"]
- plugin_test:
- description: >
- Checks that the project template works and supports plugins.
- stage: devicelab
- required_agent_capabilities: ["linux/android"]
- flaky: true
-
flutter_gallery_instrumentation_test:
description: >
Same as flutter_gallery__transition_perf but uses Android instrumentation
@@ -260,13 +253,6 @@
stage: devicelab_ios
required_agent_capabilities: ["mac/ios"]
- plugin_test_ios:
- description: >
- Checks that the project template works and supports plugins on iOS.
- stage: devicelab_ios
- required_agent_capabilities: ["mac/ios"]
- flaky: true
-
external_ui_integration_test_ios:
description: >
Checks that external UIs work on iOS.
@@ -361,13 +347,6 @@
stage: devicelab_win
required_agent_capabilities: ["windows/android"]
- plugin_test_win:
- description: >
- Checks that the project template works and supports plugins on Windows.
- stage: devicelab_win
- required_agent_capabilities: ["windows/android"]
- flaky: true
-
hot_mode_dev_cycle_win__benchmark:
description: >
Measures the performance of Dart VM hot patching feature on Windows.
diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart
index 8312408..e9598b6 100644
--- a/packages/flutter_tools/lib/src/android/gradle.dart
+++ b/packages/flutter_tools/lib/src/android/gradle.dart
@@ -16,6 +16,7 @@
import '../build_info.dart';
import '../cache.dart';
import '../globals.dart';
+import '../plugins.dart';
import 'android_sdk.dart';
import 'android_studio.dart';
@@ -93,6 +94,7 @@
Future<GradleProject> _readGradleProject() async {
final String gradle = await _ensureGradle();
updateLocalProperties();
+ injectPlugins();
try {
final Status status = logger.startProgress('Resolving dependencies...', expectSlowOperation: true);
final RunResult runResult = await runCheckedAsync(
diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart
index ea4e9dc3..f98dd46a 100644
--- a/packages/flutter_tools/lib/src/application_package.dart
+++ b/packages/flutter_tools/lib/src/application_package.dart
@@ -181,11 +181,11 @@
if (id == null)
return null;
final String projectPath = fs.path.join('ios', 'Runner.xcodeproj');
- final Map<String, String> buildSettings = xcodeProjectInterpreter.getBuildSettings(projectPath, 'Runner');
+ final Map<String, String> buildSettings = getXcodeBuildSettings(projectPath, 'Runner');
id = substituteXcodeVariables(id, buildSettings);
return new BuildableIOSApp(
- appDirectory: 'ios',
+ appDirectory: fs.path.join('ios'),
projectBundleId: id,
buildSettings: buildSettings,
);
diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart
index 5956021..643a452 100644
--- a/packages/flutter_tools/lib/src/commands/create.dart
+++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -14,10 +14,14 @@
import '../base/file_system.dart';
import '../base/os.dart';
import '../base/utils.dart';
+import '../build_info.dart';
import '../cache.dart';
import '../dart/pub.dart';
import '../doctor.dart';
+import '../flx.dart' as flx;
import '../globals.dart';
+import '../ios/xcodeproj.dart';
+import '../plugins.dart';
import '../project.dart';
import '../runner/flutter_command.dart';
import '../template.dart';
@@ -228,9 +232,17 @@
printStatus('Wrote $generatedCount files.');
printStatus('');
+ updateXcodeGeneratedProperties(
+ projectPath: appPath,
+ buildInfo: BuildInfo.debug,
+ target: flx.defaultMainPath,
+ hasPlugins: generatePlugin,
+ previewDart2: false,
+ );
+
if (argResults['pub']) {
await pubGet(context: PubContext.create, directory: appPath, offline: argResults['offline']);
- new FlutterProject(fs.directory(appPath)).ensureReadyForPlatformSpecificTooling();
+ injectPlugins(directory: appPath);
}
if (android_sdk.androidSdk != null)
diff --git a/packages/flutter_tools/lib/src/commands/inject_plugins.dart b/packages/flutter_tools/lib/src/commands/inject_plugins.dart
index 6886937..f1df432 100644
--- a/packages/flutter_tools/lib/src/commands/inject_plugins.dart
+++ b/packages/flutter_tools/lib/src/commands/inject_plugins.dart
@@ -24,8 +24,7 @@
@override
Future<Null> runCommand() async {
- injectPlugins();
- final bool result = hasPlugins();
+ final bool result = injectPlugins().hasPlugin;
if (result) {
printStatus('GeneratedPluginRegistrants successfully written.');
} else {
diff --git a/packages/flutter_tools/lib/src/commands/packages.dart b/packages/flutter_tools/lib/src/commands/packages.dart
index 3600289..44aafbc 100644
--- a/packages/flutter_tools/lib/src/commands/packages.dart
+++ b/packages/flutter_tools/lib/src/commands/packages.dart
@@ -5,10 +5,8 @@
import 'dart:async';
import '../base/common.dart';
-import '../base/file_system.dart';
import '../base/os.dart';
import '../dart/pub.dart';
-import '../project.dart';
import '../runner/flutter_command.dart';
class PackagesCommand extends FlutterCommand {
@@ -77,7 +75,6 @@
offline: argResults['offline'],
checkLastModified: false,
);
- new FlutterProject(fs.directory(target)).ensureReadyForPlatformSpecificTooling();
}
}
diff --git a/packages/flutter_tools/lib/src/ios/cocoapods.dart b/packages/flutter_tools/lib/src/ios/cocoapods.dart
index 1d558d4..da63cdc 100644
--- a/packages/flutter_tools/lib/src/ios/cocoapods.dart
+++ b/packages/flutter_tools/lib/src/ios/cocoapods.dart
@@ -16,7 +16,6 @@
import '../base/version.dart';
import '../cache.dart';
import '../globals.dart';
-import 'xcodeproj.dart';
const String noCocoaPodsConsequence = '''
CocoaPods is used to retrieve the iOS platform side's plugin code that responds to your plugin usage on the Dart side.
@@ -61,13 +60,13 @@
// For backward compatibility with previously created Podfile only.
@required String iosEngineDir,
bool isSwift: false,
- bool flutterPodChanged: true,
+ bool pluginOrFlutterPodChanged: true,
}) async {
- if (!(await appIosDir.childFile('Podfile').exists())) {
- throwToolExit('Podfile missing');
- }
if (await _checkPodCondition()) {
- if (_shouldRunPodInstall(appIosDir.path, flutterPodChanged))
+ if (!fs.file(fs.path.join(appIosDir.path, 'Podfile')).existsSync()) {
+ await _createPodfile(appIosDir, isSwift);
+ } // TODO(xster): Add more logic for handling merge conflicts.
+ if (_shouldRunPodInstall(appIosDir.path, pluginOrFlutterPodChanged))
await _runPodInstall(appIosDir, iosEngineDir);
}
}
@@ -100,69 +99,39 @@
return true;
}
- /// Ensures the `ios` sub-project of the Flutter project at [directory]
- /// contains a suitable `Podfile` and that its `Flutter/Xxx.xcconfig` files
- /// include pods configuration.
- void setupPodfile(String directory) {
- if (!xcodeProjectInterpreter.canInterpretXcodeProjects) {
- // Don't do anything for iOS when host platform doesn't support it.
- return;
- }
- final String podfilePath = fs.path.join(directory, 'ios', 'Podfile');
- if (!fs.file(podfilePath).existsSync()) {
- final bool isSwift = xcodeProjectInterpreter.getBuildSettings(
- fs.path.join(directory, 'ios', 'Runner.xcodeproj'),
- 'Runner',
- ).containsKey('SWIFT_VERSION');
- final File podfileTemplate = fs.file(fs.path.join(
- Cache.flutterRoot,
- 'packages',
- 'flutter_tools',
- 'templates',
- 'cocoapods',
- isSwift ? 'Podfile-swift' : 'Podfile-objc',
- ));
- podfileTemplate.copySync(podfilePath);
- }
- _addPodsDependencyToFlutterXcconfig(directory, 'Debug');
- _addPodsDependencyToFlutterXcconfig(directory, 'Release');
- }
-
- void _addPodsDependencyToFlutterXcconfig(String directory, String mode) {
- final File file = fs.file(fs.path.join(directory, 'ios', 'Flutter', '$mode.xcconfig'));
- if (file.existsSync()) {
- final String content = file.readAsStringSync();
- final String include = '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.${mode
- .toLowerCase()}.xcconfig"';
- if (!content.contains(include))
- file.writeAsStringSync('$include\n$content', flush: true);
- }
- }
-
- /// Ensures that pod install is deemed needed on next check.
- void invalidatePodInstallOutput(String directory) {
- final File manifest = fs.file(
- fs.path.join(directory, 'ios', 'Pods', 'Manifest.lock'),
- );
- if (manifest.existsSync())
- manifest.deleteSync();
+ Future<Null> _createPodfile(Directory bundle, bool isSwift) async {
+ final File podfileTemplate = fs.file(fs.path.join(
+ Cache.flutterRoot,
+ 'packages',
+ 'flutter_tools',
+ 'templates',
+ 'cocoapods',
+ isSwift ? 'Podfile-swift' : 'Podfile-objc',
+ ));
+ podfileTemplate.copySync(fs.path.join(bundle.path, 'Podfile'));
}
// Check if you need to run pod install.
// The pod install will run if any of below is true.
- // 1. The flutter.framework has changed (debug/release/profile)
- // 2. The podfile.lock doesn't exist
- // 3. The Pods/Manifest.lock doesn't exist (It is deleted when plugins change)
- // 4. The podfile.lock doesn't match Pods/Manifest.lock.
- bool _shouldRunPodInstall(String appDir, bool flutterPodChanged) {
- if (flutterPodChanged)
+ // 1. Any plugins changed (add/update/delete)
+ // 2. The flutter.framework has changed (debug/release/profile)
+ // 3. The podfile.lock doesn't exists
+ // 4. The Pods/manifest.lock doesn't exists
+ // 5. The podfile.lock doesn't match Pods/manifest.lock.
+ bool _shouldRunPodInstall(String appDir, bool pluginOrFlutterPodChanged) {
+ if (pluginOrFlutterPodChanged)
return true;
- // Check if podfile.lock and Pods/Manifest.lock exist and match.
+ // Check if podfile.lock and Pods/Manifest.lock exists and matches.
final File podfileLockFile = fs.file(fs.path.join(appDir, 'Podfile.lock'));
- final File manifestLockFile = fs.file(fs.path.join(appDir, 'Pods', 'Manifest.lock'));
- return !podfileLockFile.existsSync()
+ final File manifestLockFile =
+ fs.file(fs.path.join(appDir, 'Pods', 'Manifest.lock'));
+ if (!podfileLockFile.existsSync()
|| !manifestLockFile.existsSync()
- || podfileLockFile.readAsStringSync() != manifestLockFile.readAsStringSync();
+ || podfileLockFile.readAsStringSync() !=
+ manifestLockFile.readAsStringSync()) {
+ return true;
+ }
+ return false;
}
Future<Null> _runPodInstall(Directory bundle, String engineDirectory) async {
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index 9f174f0..621186d 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -217,7 +217,7 @@
return new XcodeBuildResult(success: false);
}
- final XcodeProjectInfo projectInfo = xcodeProjectInterpreter.getInfo(app.appDirectory);
+ final XcodeProjectInfo projectInfo = new XcodeProjectInfo.fromProjectSync(app.appDirectory);
if (!projectInfo.targets.contains('Runner')) {
printError('The Xcode project does not define target "Runner" which is needed by Flutter tooling.');
printError('Open Xcode to fix the problem:');
@@ -254,22 +254,26 @@
// copied over to a location that is suitable for Xcodebuild to find them.
final Directory appDirectory = fs.directory(app.appDirectory);
await _addServicesToBundle(appDirectory);
+ final InjectPluginsResult injectPluginsResult = injectPlugins();
+ final bool hasFlutterPlugins = injectPluginsResult.hasPlugin;
final String previousGeneratedXcconfig = readGeneratedXcconfig(app.appDirectory);
- updateGeneratedXcodeProperties(
+ updateXcodeGeneratedProperties(
projectPath: fs.currentDirectory.path,
buildInfo: buildInfo,
target: target,
+ hasPlugins: hasFlutterPlugins,
previewDart2: buildInfo.previewDart2,
);
- if (hasPlugins()) {
+ if (hasFlutterPlugins) {
final String currentGeneratedXcconfig = readGeneratedXcconfig(app.appDirectory);
await cocoaPods.processPods(
- appIosDir: appDirectory,
- iosEngineDir: flutterFrameworkDir(buildInfo.mode),
- isSwift: app.isSwift,
- flutterPodChanged: (previousGeneratedXcconfig != currentGeneratedXcconfig),
+ appIosDir: appDirectory,
+ iosEngineDir: flutterFrameworkDir(buildInfo.mode),
+ isSwift: app.isSwift,
+ pluginOrFlutterPodChanged: (injectPluginsResult.hasChanged
+ || previousGeneratedXcconfig != currentGeneratedXcconfig),
);
}
@@ -415,7 +419,7 @@
String readGeneratedXcconfig(String appPath) {
final String generatedXcconfigPath =
- fs.path.join(fs.currentDirectory.path, appPath, 'Flutter', 'Generated.xcconfig');
+ fs.path.join(fs.currentDirectory.path, appPath, 'Flutter','Generated.xcconfig');
final File generatedXcconfigFile = fs.file(generatedXcconfigPath);
if (!generatedXcconfigFile.existsSync())
return null;
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
index 9a50d30..1bc8e79 100644
--- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart
+++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -5,13 +5,11 @@
import 'package:meta/meta.dart';
import '../artifacts.dart';
-import '../base/context.dart';
import '../base/file_system.dart';
import '../base/process.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../cache.dart';
-import '../flx.dart' as flx;
import '../globals.dart';
final RegExp _settingExpr = new RegExp(r'(\w+)\s*=\s*(.*)$');
@@ -21,28 +19,11 @@
return fs.path.normalize(fs.path.dirname(artifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, mode)));
}
-String _generatedXcodePropertiesPath(String projectPath) {
- return fs.path.join(projectPath, 'ios', 'Flutter', 'Generated.xcconfig');
-}
-
-/// Writes default Xcode properties files in the Flutter project at
-/// [projectPath], if such files do not already exist.
-void generateXcodeProperties(String projectPath) {
- if (fs.file(_generatedXcodePropertiesPath(projectPath)).existsSync())
- return;
- updateGeneratedXcodeProperties(
- projectPath: projectPath,
- buildInfo: BuildInfo.debug,
- target: flx.defaultMainPath,
- previewDart2: false,
- );
-}
-
-/// Writes or rewrites Xcode property files with the specified information.
-void updateGeneratedXcodeProperties({
+void updateXcodeGeneratedProperties({
@required String projectPath,
@required BuildInfo buildInfo,
@required String target,
+ @required bool hasPlugins,
@required bool previewDart2,
}) {
final StringBuffer localsBuffer = new StringBuffer();
@@ -77,42 +58,21 @@
localsBuffer.writeln('PREVIEW_DART_2=true');
}
- final File localsFile = fs.file(_generatedXcodePropertiesPath(projectPath));
+ // Add dependency to CocoaPods' generated project only if plugins are used.
+ if (hasPlugins)
+ localsBuffer.writeln('#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"');
+
+ final File localsFile = fs.file(fs.path.join(projectPath, 'ios', 'Flutter', 'Generated.xcconfig'));
localsFile.createSync(recursive: true);
localsFile.writeAsStringSync(localsBuffer.toString());
}
-XcodeProjectInterpreter get xcodeProjectInterpreter => context.putIfAbsent(
- XcodeProjectInterpreter,
- () => const XcodeProjectInterpreter(),
-);
-
-/// Interpreter of Xcode projects settings.
-class XcodeProjectInterpreter {
- static const String _executable = '/usr/bin/xcodebuild';
-
- const XcodeProjectInterpreter();
-
- bool get canInterpretXcodeProjects => fs.isFileSync(_executable);
-
- Map<String, String> getBuildSettings(String projectPath, String target) {
- final String out = runCheckedSync(<String>[
- _executable,
- '-project',
- fs.path.absolute(projectPath),
- '-target',
- target,
- '-showBuildSettings'
- ], workingDirectory: projectPath);
- return parseXcodeBuildSettings(out);
- }
-
- XcodeProjectInfo getInfo(String projectPath) {
- final String out = runCheckedSync(<String>[
- _executable, '-list',
- ], workingDirectory: projectPath);
- return new XcodeProjectInfo.fromXcodeBuildOutput(out);
- }
+Map<String, String> getXcodeBuildSettings(String xcodeProjPath, String target) {
+ final String absProjPath = fs.path.absolute(xcodeProjPath);
+ final String out = runCheckedSync(<String>[
+ '/usr/bin/xcodebuild', '-project', absProjPath, '-target', target, '-showBuildSettings'
+ ]);
+ return parseXcodeBuildSettings(out);
}
Map<String, String> parseXcodeBuildSettings(String showBuildSettingsOutput) {
@@ -141,6 +101,13 @@
class XcodeProjectInfo {
XcodeProjectInfo(this.targets, this.buildConfigurations, this.schemes);
+ factory XcodeProjectInfo.fromProjectSync(String projectPath) {
+ final String out = runCheckedSync(<String>[
+ '/usr/bin/xcodebuild', '-list',
+ ], workingDirectory: projectPath);
+ return new XcodeProjectInfo.fromXcodeBuildOutput(out);
+ }
+
factory XcodeProjectInfo.fromXcodeBuildOutput(String output) {
final List<String> targets = <String>[];
final List<String> buildConfigurations = <String>[];
diff --git a/packages/flutter_tools/lib/src/plugins.dart b/packages/flutter_tools/lib/src/plugins.dart
index 697cfdc..0d03f04 100644
--- a/packages/flutter_tools/lib/src/plugins.dart
+++ b/packages/flutter_tools/lib/src/plugins.dart
@@ -9,7 +9,6 @@
import 'base/file_system.dart';
import 'dart/package_map.dart';
import 'globals.dart';
-import 'ios/cocoapods.dart';
class Plugin {
final String name;
@@ -81,25 +80,21 @@
/// Returns true if .flutter-plugins has changed, otherwise returns false.
bool _writeFlutterPluginsList(String directory, List<Plugin> plugins) {
- final File pluginsFile = fs.file(fs.path.join(directory, '.flutter-plugins'));
- final String oldContents = _readFlutterPluginsList(directory);
+ final File pluginsProperties = fs.file(fs.path.join(directory, '.flutter-plugins'));
+ final String previousFlutterPlugins =
+ pluginsProperties.existsSync() ? pluginsProperties.readAsStringSync() : null;
final String pluginManifest =
plugins.map((Plugin p) => '${p.name}=${escapePath(p.path)}').join('\n');
if (pluginManifest.isNotEmpty) {
- pluginsFile.writeAsStringSync('$pluginManifest\n', flush: true);
+ pluginsProperties.writeAsStringSync('$pluginManifest\n');
} else {
- if (pluginsFile.existsSync())
- pluginsFile.deleteSync();
+ if (pluginsProperties.existsSync()) {
+ pluginsProperties.deleteSync();
+ }
}
- final String newContents = _readFlutterPluginsList(directory);
- return oldContents != newContents;
-}
-
-/// Returns the contents of the `.flutter-plugins` file in [directory], or
-/// null if that file does not exist.
-String _readFlutterPluginsList(String directory) {
- final File pluginsFile = fs.file(fs.path.join(directory, '.flutter-plugins'));
- return pluginsFile.existsSync() ? pluginsFile.readAsStringSync() : null;
+ final String currentFlutterPlugins =
+ pluginsProperties.existsSync() ? pluginsProperties.readAsStringSync() : null;
+ return currentFlutterPlugins != previousFlutterPlugins;
}
const String _androidPluginRegistryTemplate = '''package io.flutter.plugins;
@@ -133,7 +128,7 @@
}
''';
-void _writeAndroidPluginRegistrant(String directory, List<Plugin> plugins) {
+void _writeAndroidPluginRegistry(String directory, List<Plugin> plugins) {
final List<Map<String, dynamic>> androidPlugins = plugins
.where((Plugin p) => p.androidPackage != null && p.pluginClass != null)
.map((Plugin p) => <String, dynamic>{
@@ -192,7 +187,7 @@
@end
''';
-void _writeIOSPluginRegistrant(String directory, List<Plugin> plugins) {
+void _writeIOSPluginRegistry(String directory, List<Plugin> plugins) {
final List<Map<String, dynamic>> iosPlugins = plugins
.where((Plugin p) => p.pluginClass != null)
.map((Plugin p) => <String, dynamic>{
@@ -215,6 +210,7 @@
registryHeaderFile.writeAsStringSync(pluginRegistryHeader);
final File registryImplementationFile = registryDirectory.childFile('GeneratedPluginRegistrant.m');
registryImplementationFile.writeAsStringSync(pluginRegistryImplementation);
+
}
class InjectPluginsResult{
@@ -228,30 +224,17 @@
final bool hasChanged;
}
-/// Injects plugins found in `pubspec.yaml` into the platform-specific projects.
-void injectPlugins({String directory}) {
+/// Finds Flutter plugins in the pubspec.yaml, creates platform injection
+/// registries classes and add them to the build dependencies.
+///
+/// Returns whether any Flutter plugins are added and whether they changed.
+InjectPluginsResult injectPlugins({String directory}) {
directory ??= fs.currentDirectory.path;
- if (fs.file(fs.path.join(directory, 'example', 'pubspec.yaml')).existsSync()) {
- // Switch to example app if in plugin project template.
- directory = fs.path.join(directory, 'example');
- }
final List<Plugin> plugins = _findPlugins(directory);
- final bool changed = _writeFlutterPluginsList(directory, plugins);
+ final bool hasPluginsChanged = _writeFlutterPluginsList(directory, plugins);
if (fs.isDirectorySync(fs.path.join(directory, 'android')))
- _writeAndroidPluginRegistrant(directory, plugins);
- if (fs.isDirectorySync(fs.path.join(directory, 'ios'))) {
- _writeIOSPluginRegistrant(directory, plugins);
- final CocoaPods cocoaPods = const CocoaPods();
- if (plugins.isNotEmpty)
- cocoaPods.setupPodfile(directory);
- if (changed)
- cocoaPods.invalidatePodInstallOutput(directory);
- }
-}
-
-/// Returns whether the Flutter project at the specified [directory]
-/// has any plugin dependencies.
-bool hasPlugins({String directory}) {
- directory ??= fs.currentDirectory.path;
- return _readFlutterPluginsList(directory) != null;
+ _writeAndroidPluginRegistry(directory, plugins);
+ if (fs.isDirectorySync(fs.path.join(directory, 'ios')))
+ _writeIOSPluginRegistry(directory, plugins);
+ return new InjectPluginsResult(hasPlugin: plugins.isNotEmpty, hasChanged: hasPluginsChanged);
}
diff --git a/packages/flutter_tools/lib/src/project.dart b/packages/flutter_tools/lib/src/project.dart
index 7800f2a..1fd1b4f 100644
--- a/packages/flutter_tools/lib/src/project.dart
+++ b/packages/flutter_tools/lib/src/project.dart
@@ -4,11 +4,7 @@
import 'dart:async';
import 'dart:convert';
-
import 'base/file_system.dart';
-import 'ios/xcodeproj.dart';
-import 'plugins.dart';
-
/// Represents the contents of a Flutter project at the specified [directory].
class FlutterProject {
@@ -47,25 +43,8 @@
/// The Android sub project of this project.
AndroidProject get android => new AndroidProject(directory.childDirectory('android'));
- /// Returns true if this project is a plugin project.
- bool get isPluginProject => directory.childDirectory('example').childFile('pubspec.yaml').existsSync();
-
/// The example sub project of this (plugin) project.
FlutterProject get example => new FlutterProject(directory.childDirectory('example'));
-
- /// Generates project files necessary to make Gradle builds work on Android
- /// and CocoaPods+Xcode work on iOS.
- void ensureReadyForPlatformSpecificTooling() {
- if (!directory.existsSync()) {
- return;
- }
- if (isPluginProject) {
- example.ensureReadyForPlatformSpecificTooling();
- } else {
- injectPlugins(directory: directory.path);
- generateXcodeProperties(directory.path);
- }
- }
}
/// Represents the contents of the ios/ folder of a Flutter project.
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index ca48a1a..9d08b3e 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -21,7 +21,6 @@
import '../doctor.dart';
import '../flx.dart' as flx;
import '../globals.dart';
-import '../project.dart';
import '../usage.dart';
import 'flutter_command_runner.dart';
@@ -273,10 +272,8 @@
if (shouldUpdateCache)
await cache.updateAll();
- if (shouldRunPub) {
+ if (shouldRunPub)
await pubGet(context: PubContext.getVerifyContext(name));
- new FlutterProject(fs.currentDirectory).ensureReadyForPlatformSpecificTooling();
- }
setupApplicationPackages();
diff --git a/packages/flutter_tools/test/commands/packages_test.dart b/packages/flutter_tools/test/commands/packages_test.dart
index 42bd5c2..86bbc28 100644
--- a/packages/flutter_tools/test/commands/packages_test.dart
+++ b/packages/flutter_tools/test/commands/packages_test.dart
@@ -29,19 +29,9 @@
temp.deleteSync(recursive: true);
});
- Future<String> createProjectWithPlugin(String plugin) async {
+ Future<String> runCommand(String verb, { List<String> args }) async {
final String projectPath = await createProject(temp);
- final File pubspec = fs.file(fs.path.join(projectPath, 'pubspec.yaml'));
- String content = await pubspec.readAsString();
- content = content.replaceFirst(
- '\ndependencies:\n',
- '\ndependencies:\n $plugin:\n',
- );
- await pubspec.writeAsString(content, flush: true);
- return projectPath;
- }
- Future<Null> runCommandIn(String projectPath, String verb, { List<String> args }) async {
final PackagesCommand command = new PackagesCommand();
final CommandRunner<Null> runner = createTestCommandRunner(command);
@@ -51,138 +41,31 @@
commandArgs.add(projectPath);
await runner.run(commandArgs);
+
+ return projectPath;
}
void expectExists(String projectPath, String relPath) {
expect(fs.isFileSync(fs.path.join(projectPath, relPath)), true);
}
- void expectContains(String projectPath, String relPath, String substring) {
- expectExists(projectPath, relPath);
- expect(
- fs.file(fs.path.join(projectPath, relPath)).readAsStringSync(),
- contains(substring),
- );
- }
-
- void expectNotExists(String projectPath, String relPath) {
- expect(fs.isFileSync(fs.path.join(projectPath, relPath)), false);
- }
-
- void expectNotContains(String projectPath, String relPath, String substring) {
- expectExists(projectPath, relPath);
- expect(
- fs.file(fs.path.join(projectPath, relPath)).readAsStringSync(),
- isNot(contains(substring)),
- );
- }
-
- const List<String> pubOutput = const <String>[
- '.packages',
- 'pubspec.lock',
- ];
-
- const List<String> pluginRegistrants = const <String>[
- 'ios/Runner/GeneratedPluginRegistrant.h',
- 'ios/Runner/GeneratedPluginRegistrant.m',
- 'android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java',
- ];
-
- const List<String> pluginWitnesses = const <String>[
- '.flutter-plugins',
- 'ios/Podfile',
- ];
-
- const Map<String, String> pluginContentWitnesses = const <String, String>{
- 'ios/Flutter/Debug.xcconfig': '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"',
- 'ios/Flutter/Release.xcconfig': '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"',
- };
-
- void expectDependenciesResolved(String projectPath) {
- for (String output in pubOutput) {
- expectExists(projectPath, output);
- }
- }
-
- void expectZeroPluginsInjected(String projectPath) {
- for (final String registrant in pluginRegistrants) {
- expectExists(projectPath, registrant);
- }
- for (final String witness in pluginWitnesses) {
- expectNotExists(projectPath, witness);
- }
- pluginContentWitnesses.forEach((String witness, String content) {
- expectNotContains(projectPath, witness, content);
- });
- }
-
- void expectPluginInjected(String projectPath) {
- for (final String registrant in pluginRegistrants) {
- expectExists(projectPath, registrant);
- }
- for (final String witness in pluginWitnesses) {
- expectExists(projectPath, witness);
- }
- pluginContentWitnesses.forEach((String witness, String content) {
- expectContains(projectPath, witness, content);
- });
- }
-
- void removeGeneratedFiles(String projectPath) {
- final Iterable<String> allFiles = <List<String>>[
- pubOutput,
- pluginRegistrants,
- pluginWitnesses,
- ].expand((List<String> list) => list);
- for (String path in allFiles) {
- final File file = fs.file(fs.path.join(projectPath, path));
- if (file.existsSync())
- file.deleteSync();
- }
- }
-
- testUsingContext('get fetches packages', () async {
- final String projectPath = await createProject(temp);
-
- removeGeneratedFiles(projectPath);
-
- await runCommandIn(projectPath, 'get');
-
- expectDependenciesResolved(projectPath);
- expectZeroPluginsInjected(projectPath);
+ // Verify that we create a project that is well-formed.
+ testUsingContext('get', () async {
+ final String projectPath = await runCommand('get');
+ expectExists(projectPath, 'lib/main.dart');
+ expectExists(projectPath, '.packages');
}, timeout: allowForRemotePubInvocation);
- testUsingContext('get --offline fetches packages', () async {
- final String projectPath = await createProject(temp);
+ testUsingContext('get --offline', () async {
+ final String projectPath = await runCommand('get', args: <String>['--offline']);
+ expectExists(projectPath, 'lib/main.dart');
+ expectExists(projectPath, '.packages');
+ });
- removeGeneratedFiles(projectPath);
-
- await runCommandIn(projectPath, 'get', args: <String>['--offline']);
-
- expectDependenciesResolved(projectPath);
- expectZeroPluginsInjected(projectPath);
- }, timeout: allowForCreateFlutterProject);
-
- testUsingContext('upgrade fetches packages', () async {
- final String projectPath = await createProject(temp);
-
- removeGeneratedFiles(projectPath);
-
- await runCommandIn(projectPath, 'upgrade');
-
- expectDependenciesResolved(projectPath);
- expectZeroPluginsInjected(projectPath);
- }, timeout: allowForRemotePubInvocation);
-
- testUsingContext('get fetches packages and injects plugin', () async {
- final String projectPath = await createProjectWithPlugin('path_provider');
-
- removeGeneratedFiles(projectPath);
-
- await runCommandIn(projectPath, 'get');
-
- expectDependenciesResolved(projectPath);
- expectPluginInjected(projectPath);
+ testUsingContext('upgrade', () async {
+ final String projectPath = await runCommand('upgrade');
+ expectExists(projectPath, 'lib/main.dart');
+ expectExists(projectPath, '.packages');
}, timeout: allowForRemotePubInvocation);
});
diff --git a/packages/flutter_tools/test/ios/cocoapods_test.dart b/packages/flutter_tools/test/ios/cocoapods_test.dart
index 77c1e6d..531c8ab 100644
--- a/packages/flutter_tools/test/ios/cocoapods_test.dart
+++ b/packages/flutter_tools/test/ios/cocoapods_test.dart
@@ -6,11 +6,9 @@
import 'package:file/file.dart';
import 'package:file/memory.dart';
-import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/io.dart';
-import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/ios/cocoapods.dart';
-import 'package:flutter_tools/src/ios/xcodeproj.dart';
+import 'package:flutter_tools/src/cache.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import 'package:test/test.dart';
@@ -20,7 +18,6 @@
void main() {
FileSystem fs;
ProcessManager mockProcessManager;
- MockXcodeProjectInterpreter mockXcodeProjectInterpreter;
Directory projectUnderTest;
CocoaPods cocoaPodsUnderTest;
@@ -28,9 +25,7 @@
Cache.flutterRoot = 'flutter';
fs = new MemoryFileSystem();
mockProcessManager = new MockProcessManager();
- mockXcodeProjectInterpreter = new MockXcodeProjectInterpreter();
projectUnderTest = fs.directory(fs.path.join('project', 'ios'))..createSync(recursive: true);
-
fs.file(fs.path.join(
Cache.flutterRoot, 'packages', 'flutter_tools', 'templates', 'cocoapods', 'Podfile-objc'
))
@@ -50,122 +45,97 @@
)).thenReturn(exitsHappy);
});
- group('Setup Podfile', () {
- File podfile;
- File debugConfigFile;
- File releaseConfigFile;
-
- setUp(() {
- debugConfigFile = fs.file(fs.path.join('project', 'ios', 'Flutter', 'Debug.xcconfig'));
- releaseConfigFile = fs.file(fs.path.join('project', 'ios', 'Flutter', 'Release.xcconfig'));
- podfile = fs.file(fs.path.join('project', 'ios', 'Podfile'));
- });
-
- testUsingContext('creates objective-c Podfile when not present', () {
- cocoaPodsUnderTest.setupPodfile('project');
-
- expect(podfile.readAsStringSync(), 'Objective-C podfile template');
- }, overrides: <Type, Generator>{
- FileSystem: () => fs,
- });
-
- testUsingContext('creates swift Podfile if swift', () {
- when(mockXcodeProjectInterpreter.canInterpretXcodeProjects).thenReturn(true);
- when(mockXcodeProjectInterpreter.getBuildSettings(any, any)).thenReturn(<String, String>{
- 'SWIFT_VERSION': '4.0',
- });
-
- cocoaPodsUnderTest.setupPodfile('project');
-
- expect(podfile.readAsStringSync(), 'Swift podfile template');
- }, overrides: <Type, Generator>{
- FileSystem: () => fs,
- XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
- });
-
- testUsingContext('does not recreate Podfile when already present', () {
- podfile..createSync()..writeAsStringSync('Existing Podfile');
-
- cocoaPodsUnderTest.setupPodfile('project');
-
- expect(podfile.readAsStringSync(), 'Existing Podfile');
- }, overrides: <Type, Generator>{
- FileSystem: () => fs,
- });
-
- testUsingContext('does not create Podfile when we cannot interpret Xcode projects', () {
- when(mockXcodeProjectInterpreter.canInterpretXcodeProjects).thenReturn(false);
-
- cocoaPodsUnderTest.setupPodfile('project');
-
- expect(podfile.existsSync(), false);
- }, overrides: <Type, Generator>{
- FileSystem: () => fs,
- XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
- });
-
- testUsingContext('includes Pod config in xcconfig files, if not present', () {
- podfile..createSync()..writeAsStringSync('Existing Podfile');
- debugConfigFile..createSync(recursive: true)..writeAsStringSync('Existing debug config');
- releaseConfigFile..createSync(recursive: true)..writeAsStringSync('Existing release config');
-
- cocoaPodsUnderTest.setupPodfile('project');
-
- final String debugContents = debugConfigFile.readAsStringSync();
- expect(debugContents, contains(
- '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"\n'));
- expect(debugContents, contains('Existing debug config'));
- final String releaseContents = releaseConfigFile.readAsStringSync();
- expect(releaseContents, contains(
- '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"\n'));
- expect(releaseContents, contains('Existing release config'));
- }, overrides: <Type, Generator>{
- FileSystem: () => fs,
- });
- });
-
- group('Process pods', () {
- testUsingContext('prints error, if CocoaPods is not installed', () async {
- projectUnderTest.childFile('Podfile').createSync();
- cocoaPodsUnderTest = const TestCocoaPods(false);
+ testUsingContext(
+ 'create objective-c Podfile when not present',
+ () async {
await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest,
iosEngineDir: 'engine/path',
);
- verifyNever(mockProcessManager.run(
- typed<List<String>>(any),
- workingDirectory: any,
- environment: typed<Map<String, String>>(any, named: 'environment'),
+ expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Objective-C podfile template');
+ verify(mockProcessManager.run(
+ <String>['pod', 'install', '--verbose'],
+ workingDirectory: 'project/ios',
+ environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
));
- expect(testLogger.errorText, contains('not installed'));
- expect(testLogger.errorText, contains('Skipping pod install'));
- }, overrides: <Type, Generator>{
+ },
+ overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
- });
+ },
+ );
- testUsingContext('throws, if Podfile is missing.', () async {
- cocoaPodsUnderTest = const TestCocoaPods(true);
+ testUsingContext(
+ 'create swift Podfile if swift',
+ () async {
+ await cocoaPodsUnderTest.processPods(
+ appIosDir: projectUnderTest,
+ iosEngineDir: 'engine/path',
+ isSwift: true,
+ );
+ expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Swift podfile template');
+ verify(mockProcessManager.run(
+ <String>['pod', 'install', '--verbose'],
+ workingDirectory: 'project/ios',
+ environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
+ ));
+ },
+ overrides: <Type, Generator>{
+ FileSystem: () => fs,
+ ProcessManager: () => mockProcessManager,
+ },
+ );
+
+ testUsingContext(
+ 'do not recreate Podfile when present',
+ () async {
+ fs.file(fs.path.join('project', 'ios', 'Podfile'))
+ ..createSync()
+ ..writeAsString('Existing Podfile');
+ await cocoaPodsUnderTest.processPods(
+ appIosDir: projectUnderTest,
+ iosEngineDir: 'engine/path',
+ );
+ expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Existing Podfile');
+ verify(mockProcessManager.run(
+ <String>['pod', 'install', '--verbose'],
+ workingDirectory: 'project/ios',
+ environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
+ ));
+ },
+ overrides: <Type, Generator>{
+ FileSystem: () => fs,
+ ProcessManager: () => mockProcessManager,
+ },
+ );
+
+ testUsingContext(
+ 'missing CocoaPods throws',
+ () async {
+ cocoaPodsUnderTest = const TestCocoaPods(false);
try {
await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest,
iosEngineDir: 'engine/path',
);
- fail('ToolExit expected');
- } catch(e) {
- expect(e, const isInstanceOf<ToolExit>());
+ fail('Expected tool error');
+ } catch (ToolExit) {
verifyNever(mockProcessManager.run(
- typed<List<String>>(any),
- workingDirectory: any,
- environment: typed<Map<String, String>>(any, named: 'environment'),
+ <String>['pod', 'install', '--verbose'],
+ workingDirectory: 'project/ios',
+ environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
));
}
- }, overrides: <Type, Generator>{
+ },
+ overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
- });
+ },
+ );
- testUsingContext('throws, if specs repo is outdated.', () async {
+ testUsingContext(
+ 'outdated specs repo should print error',
+ () async {
fs.file(fs.path.join('project', 'ios', 'Podfile'))
..createSync()
..writeAsString('Existing Podfile');
@@ -173,10 +143,7 @@
when(mockProcessManager.run(
<String>['pod', 'install', '--verbose'],
workingDirectory: 'project/ios',
- environment: <String, String>{
- 'FLUTTER_FRAMEWORK_DIR': 'engine/path',
- 'COCOAPODS_DISABLE_STATS': 'true',
- },
+ environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
)).thenReturn(new ProcessResult(
1,
1,
@@ -200,152 +167,78 @@
await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest,
iosEngineDir: 'engine/path',
- );
- fail('ToolExit expected');
- } catch (e) {
- expect(e, const isInstanceOf<ToolExit>());
- expect(
- testLogger.errorText,
- contains("CocoaPods's specs repository is too out-of-date to satisfy dependencies"),
- );
+ ); expect(fs.file(fs.path.join('project', 'ios', 'Podfile')).readAsStringSync() , 'Existing Podfile');
+ fail('Exception expected');
+ } catch (ToolExit) {
+ expect(testLogger.errorText, contains("CocoaPods's specs repository is too out-of-date to satisfy dependencies"));
}
- }, overrides: <Type, Generator>{
+ },
+ overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
- });
+ },
+ );
- testUsingContext('run pod install, if Podfile.lock is missing', () async {
- projectUnderTest.childFile('Podfile')
+ testUsingContext(
+ 'Run pod install if plugins or flutter framework have changes.',
+ () async {
+ fs.file(fs.path.join('project', 'ios', 'Podfile'))
..createSync()
..writeAsString('Existing Podfile');
- projectUnderTest.childFile('Pods/Manifest.lock')
+ fs.file(fs.path.join('project', 'ios', 'Podfile.lock'))
+ ..createSync()
+ ..writeAsString('Existing lock files.');
+ fs.file(fs.path.join('project', 'ios', 'Pods','Manifest.lock'))
..createSync(recursive: true)
- ..writeAsString('Existing lock file.');
+ ..writeAsString('Existing lock files.');
await cocoaPodsUnderTest.processPods(
- appIosDir: projectUnderTest,
- iosEngineDir: 'engine/path',
- flutterPodChanged: false,
+ appIosDir: projectUnderTest,
+ iosEngineDir: 'engine/path',
+ pluginOrFlutterPodChanged: true
);
verify(mockProcessManager.run(
<String>['pod', 'install', '--verbose'],
workingDirectory: 'project/ios',
environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
));
- }, overrides: <Type, Generator>{
+ },
+ overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
- });
+ },
+ );
- testUsingContext('runs pod install, if Manifest.lock is missing', () async {
- projectUnderTest.childFile('Podfile')
+ testUsingContext(
+ 'Skip pod install if plugins and flutter framework remain unchanged.',
+ () async {
+ fs.file(fs.path.join('project', 'ios', 'Podfile'))
..createSync()
..writeAsString('Existing Podfile');
- projectUnderTest.childFile('Podfile.lock')
+ fs.file(fs.path.join('project', 'ios', 'Podfile.lock'))
..createSync()
- ..writeAsString('Existing lock file.');
- await cocoaPodsUnderTest.processPods(
- appIosDir: projectUnderTest,
- iosEngineDir: 'engine/path',
- flutterPodChanged: false,
- );
- verify(mockProcessManager.run(
- <String>['pod', 'install', '--verbose'],
- workingDirectory: 'project/ios',
- environment: <String, String>{
- 'FLUTTER_FRAMEWORK_DIR': 'engine/path',
- 'COCOAPODS_DISABLE_STATS': 'true',
- },
- ));
- }, overrides: <Type, Generator>{
- FileSystem: () => fs,
- ProcessManager: () => mockProcessManager,
- });
-
- testUsingContext('runs pod install, if Manifest.lock different from Podspec.lock', () async {
- projectUnderTest.childFile('Podfile')
- ..createSync()
- ..writeAsString('Existing Podfile');
- projectUnderTest.childFile('Podfile.lock')
- ..createSync()
- ..writeAsString('Existing lock file.');
- projectUnderTest.childFile('Pods/Manifest.lock')
+ ..writeAsString('Existing lock files.');
+ fs.file(fs.path.join('project', 'ios', 'Pods','Manifest.lock'))
..createSync(recursive: true)
- ..writeAsString('Different lock file.');
+ ..writeAsString('Existing lock files.');
await cocoaPodsUnderTest.processPods(
- appIosDir: projectUnderTest,
- iosEngineDir: 'engine/path',
- flutterPodChanged: false,
- );
- verify(mockProcessManager.run(
- <String>['pod', 'install', '--verbose'],
- workingDirectory: 'project/ios',
- environment: <String, String>{
- 'FLUTTER_FRAMEWORK_DIR': 'engine/path',
- 'COCOAPODS_DISABLE_STATS': 'true',
- },
- ));
- }, overrides: <Type, Generator>{
- FileSystem: () => fs,
- ProcessManager: () => mockProcessManager,
- });
-
- testUsingContext('runs pod install, if flutter framework changed', () async {
- projectUnderTest.childFile('Podfile')
- ..createSync()
- ..writeAsString('Existing Podfile');
- projectUnderTest.childFile('Podfile.lock')
- ..createSync()
- ..writeAsString('Existing lock file.');
- projectUnderTest.childFile('Pods/Manifest.lock')
- ..createSync(recursive: true)
- ..writeAsString('Existing lock file.');
- await cocoaPodsUnderTest.processPods(
- appIosDir: projectUnderTest,
- iosEngineDir: 'engine/path',
- flutterPodChanged: true,
- );
- verify(mockProcessManager.run(
- <String>['pod', 'install', '--verbose'],
- workingDirectory: 'project/ios',
- environment: <String, String>{
- 'FLUTTER_FRAMEWORK_DIR': 'engine/path',
- 'COCOAPODS_DISABLE_STATS': 'true',
- },
- ));
- }, overrides: <Type, Generator>{
- FileSystem: () => fs,
- ProcessManager: () => mockProcessManager,
- });
-
- testUsingContext('skips pod install, if nothing changed', () async {
- projectUnderTest.childFile('Podfile')
- ..createSync()
- ..writeAsString('Existing Podfile');
- projectUnderTest.childFile('Podfile.lock')
- ..createSync()
- ..writeAsString('Existing lock file.');
- projectUnderTest.childFile('Pods/Manifest.lock')
- ..createSync(recursive: true)
- ..writeAsString('Existing lock file.');
- await cocoaPodsUnderTest.processPods(
- appIosDir: projectUnderTest,
- iosEngineDir: 'engine/path',
- flutterPodChanged: false,
+ appIosDir: projectUnderTest,
+ iosEngineDir: 'engine/path',
+ pluginOrFlutterPodChanged: false
);
verifyNever(mockProcessManager.run(
- typed<List<String>>(any),
- workingDirectory: any,
- environment: typed<Map<String, String>>(any, named: 'environment'),
+ <String>['pod', 'install', '--verbose'],
+ workingDirectory: 'project/ios',
+ environment: <String, String>{'FLUTTER_FRAMEWORK_DIR': 'engine/path', 'COCOAPODS_DISABLE_STATS': 'true'},
));
- }, overrides: <Type, Generator>{
+ },
+ overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
- });
- });
+ },
+ );
}
class MockProcessManager extends Mock implements ProcessManager {}
-class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {}
class TestCocoaPods extends CocoaPods {
const TestCocoaPods([this._hasCocoaPods = true]);
diff --git a/packages/flutter_tools/test/project_test.dart b/packages/flutter_tools/test/project_test.dart
index 6ef5bbb..2f1a3ff 100644
--- a/packages/flutter_tools/test/project_test.dart
+++ b/packages/flutter_tools/test/project_test.dart
@@ -17,29 +17,6 @@
final Directory directory = fs.directory('myproject');
expect(new FlutterProject(directory).directory, directory);
});
- group('ensure ready for platform-specific tooling', () {
- testInMemory('does nothing, if project is not created', () async {
- final FlutterProject project = someProject();
- project.ensureReadyForPlatformSpecificTooling();
- expect(project.directory.existsSync(), isFalse);
- });
- testInMemory('injects plugins', () async {
- final FlutterProject project = aProjectWithIos();
- project.ensureReadyForPlatformSpecificTooling();
- expect(project.ios.directory.childFile('Runner/GeneratedPluginRegistrant.h').existsSync(), isTrue);
- });
- testInMemory('generates Xcode configuration', () async {
- final FlutterProject project = aProjectWithIos();
- project.ensureReadyForPlatformSpecificTooling();
- expect(project.ios.directory.childFile('Flutter/Generated.xcconfig').existsSync(), isTrue);
- });
- testInMemory('generates files in plugin example project', () async {
- final FlutterProject project = aPluginProject();
- project.ensureReadyForPlatformSpecificTooling();
- expect(project.example.ios.directory.childFile('Runner/GeneratedPluginRegistrant.h').existsSync(), isTrue);
- expect(project.example.ios.directory.childFile('Flutter/Generated.xcconfig').existsSync(), isTrue);
- });
- });
group('organization names set', () {
testInMemory('is empty, if project not created', () async {
final FlutterProject project = someProject();
@@ -94,23 +71,8 @@
});
}
-FlutterProject someProject() => new FlutterProject(fs.directory('some_project'));
-
-FlutterProject aProjectWithIos() {
- final Directory directory = fs.directory('ios_project');
- directory.childFile('pubspec.yaml').createSync(recursive: true);
- directory.childFile('.packages').createSync(recursive: true);
- directory.childDirectory('ios').createSync(recursive: true);
- return new FlutterProject(directory);
-}
-
-FlutterProject aPluginProject() {
- final Directory directory = fs.directory('plugin_project/example');
- directory.childFile('pubspec.yaml').createSync(recursive: true);
- directory.childFile('.packages').createSync(recursive: true);
- directory.childDirectory('ios').createSync(recursive: true);
- return new FlutterProject(directory.parent);
-}
+FlutterProject someProject() =>
+ new FlutterProject(fs.directory('some_project'));
void testInMemory(String description, Future<Null> testMethod()) {
testUsingContext(
@@ -122,13 +84,6 @@
);
}
-void addPubPackages(Directory directory) {
- directory.childFile('pubspec.yaml')
- ..createSync(recursive: true);
- directory.childFile('.packages')
- ..createSync(recursive: true);
-}
-
void addIosWithBundleId(Directory directory, String id) {
directory
.childDirectory('ios')
diff --git a/packages/flutter_tools/test/src/context.dart b/packages/flutter_tools/test/src/context.dart
index dbe5188..3c5fe1b 100644
--- a/packages/flutter_tools/test/src/context.dart
+++ b/packages/flutter_tools/test/src/context.dart
@@ -19,7 +19,6 @@
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/ios/mac.dart';
import 'package:flutter_tools/src/ios/simulators.dart';
-import 'package:flutter_tools/src/ios/xcodeproj.dart';
import 'package:flutter_tools/src/run_hot.dart';
import 'package:flutter_tools/src/usage.dart';
import 'package:flutter_tools/src/version.dart';
@@ -51,7 +50,6 @@
..putIfAbsent(OperatingSystemUtils, () => new MockOperatingSystemUtils())
..putIfAbsent(PortScanner, () => new MockPortScanner())
..putIfAbsent(Xcode, () => new Xcode())
- ..putIfAbsent(XcodeProjectInterpreter, () => new MockXcodeProjectInterpreter())
..putIfAbsent(IOSSimulatorUtils, () {
final MockIOSSimulatorUtils mock = new MockIOSSimulatorUtils();
when(mock.getAttachedDevices()).thenReturn(<IOSSimulator>[]);
@@ -264,25 +262,6 @@
void printWelcome() { }
}
-class MockXcodeProjectInterpreter implements XcodeProjectInterpreter {
- @override
- bool get canInterpretXcodeProjects => true;
-
- @override
- Map<String, String> getBuildSettings(String projectPath, String target) {
- return <String, String>{};
- }
-
- @override
- XcodeProjectInfo getInfo(String projectPath) {
- return new XcodeProjectInfo(
- <String>['Runner'],
- <String>['Debug', 'Release'],
- <String>['Runner'],
- );
- }
-}
-
class MockFlutterVersion extends Mock implements FlutterVersion {}
class MockClock extends Mock implements Clock {}