[go: nahoru, domu]

Skip to content

Commit

Permalink
Add .flutter-plugins-dependencies to the project, which contains th…
Browse files Browse the repository at this point in the history
…e app's plugin dependency graph (flutter#45379)
  • Loading branch information
Emmanuel Garcia committed Nov 22, 2019
1 parent 161e4df commit b6e9200
Show file tree
Hide file tree
Showing 15 changed files with 245 additions and 38 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ version
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
Expand Down
1 change: 1 addition & 0 deletions dev/integration_tests/ios_add2app/flutterapp/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ build/
.android/
.ios/
.flutter-plugins
.flutter-plugins-dependencies
1 change: 1 addition & 0 deletions dev/integration_tests/release_smoke_test/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
Expand Down
77 changes: 69 additions & 8 deletions packages/flutter_tools/gradle/flutter.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import static groovy.io.FileType.FILES

import com.android.builder.model.AndroidProject
import com.android.build.OutputFile
import groovy.json.JsonSlurper
import java.nio.file.Path
import java.nio.file.Paths
import java.util.regex.Matcher
Expand Down Expand Up @@ -253,6 +254,7 @@ class FlutterPlugin implements Plugin<Project> {
private void configurePlugins() {
if (!buildPluginAsAar()) {
getPluginList().each this.&configurePluginProject
getPluginDependencies().each this.&configurePluginDependencies
return
}
project.repositories {
Expand Down Expand Up @@ -298,19 +300,15 @@ class FlutterPlugin implements Plugin<Project> {
}

// Adds the plugin project dependency to the app project .
private void configurePluginProject(String name, String _) {
Project pluginProject = project.rootProject.findProject(":$name")
private void configurePluginProject(String pluginName, String _) {
Project pluginProject = project.rootProject.findProject(":$pluginName")
if (pluginProject == null) {
project.logger.error("Plugin project :$name not found. Please update settings.gradle.")
project.logger.error("Plugin project :$pluginName not found. Please update settings.gradle.")
return
}
// Add plugin dependency to the app project.
project.dependencies {
if (project.getConfigurations().findByName("implementation")) {
implementation pluginProject
} else {
compile pluginProject
}
implementation pluginProject
}
Closure addEmbeddingCompileOnlyDependency = { buildType ->
String flutterBuildMode = buildModeFor(buildType)
Expand All @@ -337,6 +335,36 @@ class FlutterPlugin implements Plugin<Project> {
}
}

// Add the dependencies on other plugin projects to the plugin project.
// A plugin A can depend on plugin B. As a result, this dependency must be surfaced by
// making the Gradle plugin project A depend on the Gradle plugin project B.
private void configurePluginDependencies(Object dependencyObject) {
assert dependencyObject.name instanceof String
Project pluginProject = project.rootProject.findProject(":${dependencyObject.name}")
if (pluginProject == null) {
// Ignore plugins that don't have a project since most likely they don't
// have an android/ directory.
return
}
assert dependencyObject.dependencies instanceof List
dependencyObject.dependencies.each { pluginDependencyName ->
assert pluginDependencyName instanceof String
if (pluginDependencyName.empty) {
return
}
Project dependencyProject = project.rootProject.findProject(":$pluginDependencyName")
if (dependencyProject == null) {
return
}
// Wait for the Android plugin to load and add the dependency to the plugin project.
pluginProject.afterEvaluate {
pluginProject.dependencies {
implementation dependencyProject
}
}
}
}

private Properties getPluginList() {
File pluginsFile = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins')
Properties allPlugins = readPropertiesIfExist(pluginsFile)
Expand All @@ -353,6 +381,39 @@ class FlutterPlugin implements Plugin<Project> {
return androidPlugins
}

// Gets the plugins dependencies from `.flutter-plugins-dependencies`.
private List getPluginDependencies() {
// Consider a `.flutter-plugins-dependencies` file with the following content:
// {
// "dependencyGraph": [
// {
// "name": "plugin-a",
// "dependencies": ["plugin-b","plugin-c"]
// },
// {
// "name": "plugin-b",
// "dependencies": ["plugin-c"]
// },
// {
// "name": "plugin-c",
// "dependencies": []'
// }
// ]
// }
//
// This means, `plugin-a` depends on `plugin-b` and `plugin-c`.
// `plugin-b` depends on `plugin-c`.
// `plugin-c` doesn't depend on anything.
File pluginsDependencyFile = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins-dependencies')
if (pluginsDependencyFile.exists()) {
def object = new JsonSlurper().parseText(pluginsDependencyFile.text)
assert object instanceof Map
assert object.dependencyGraph instanceof List
return object.dependencyGraph
}
return []
}

private static String toCammelCase(List<String> parts) {
if (parts.empty) {
return ""
Expand Down
105 changes: 81 additions & 24 deletions packages/flutter_tools/lib/src/plugins.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@

import 'dart:async';

import 'package:meta/meta.dart';
import 'package:mustache/mustache.dart' as mustache;
import 'package:yaml/yaml.dart';

import 'android/gradle.dart';
import 'base/common.dart';
import 'base/file_system.dart';
import 'convert.dart';
import 'dart/package_map.dart';
import 'features.dart';
import 'globals.dart';
Expand All @@ -27,10 +29,14 @@ void _renderTemplateToFile(String template, dynamic context, String filePath) {

class Plugin {
Plugin({
this.name,
this.path,
this.platforms,
});
@required this.name,
@required this.path,
@required this.platforms,
@required this.dependencies,
}) : assert(name != null),
assert(path != null),
assert(platforms != null),
assert(dependencies != null);

/// Parses [Plugin] specification from the provided pluginYaml.
///
Expand Down Expand Up @@ -60,18 +66,28 @@ class Plugin {
/// pluginClass: SamplePlugin
/// windows:
/// pluginClass: SamplePlugin
factory Plugin.fromYaml(String name, String path, YamlMap pluginYaml) {
factory Plugin.fromYaml(
String name,
String path,
YamlMap pluginYaml,
List<String> dependencies,
) {
final List<String> errors = validatePluginYaml(pluginYaml);
if (errors.isNotEmpty) {
throwToolExit('Invalid plugin specification.\n${errors.join('\n')}');
}
if (pluginYaml != null && pluginYaml['platforms'] != null) {
return Plugin._fromMultiPlatformYaml(name, path, pluginYaml);
return Plugin._fromMultiPlatformYaml(name, path, pluginYaml, dependencies);
}
return Plugin._fromLegacyYaml(name, path, pluginYaml);
return Plugin._fromLegacyYaml(name, path, pluginYaml, dependencies);
}

factory Plugin._fromMultiPlatformYaml(String name, String path, dynamic pluginYaml) {
factory Plugin._fromMultiPlatformYaml(
String name,
String path,
dynamic pluginYaml,
List<String> dependencies,
) {
assert (pluginYaml != null && pluginYaml['platforms'] != null,
'Invalid multi-platform plugin specification.');
final YamlMap platformsYaml = pluginYaml['platforms'] as YamlMap;
Expand Down Expand Up @@ -118,10 +134,16 @@ class Plugin {
name: name,
path: path,
platforms: platforms,
dependencies: dependencies,
);
}

factory Plugin._fromLegacyYaml(String name, String path, dynamic pluginYaml) {
factory Plugin._fromLegacyYaml(
String name,
String path,
dynamic pluginYaml,
List<String> dependencies,
) {
final Map<String, PluginPlatform> platforms = <String, PluginPlatform>{};
final String pluginClass = pluginYaml['pluginClass'] as String;
if (pluginYaml != null && pluginClass != null) {
Expand All @@ -147,6 +169,7 @@ class Plugin {
name: name,
path: path,
platforms: platforms,
dependencies: dependencies,
);
}

Expand Down Expand Up @@ -232,6 +255,9 @@ class Plugin {
final String name;
final String path;

/// The name of the packages this plugin depends on.
final List<String> dependencies;

/// This is a mapping from platform config key to the plugin platform spec.
final Map<String, PluginPlatform> platforms;
}
Expand All @@ -250,11 +276,13 @@ Plugin _pluginFromPubspec(String name, Uri packageRoot) {
return null;
}
final String packageRootPath = fs.path.fromUri(packageRoot);
final YamlMap dependencies = pubspec['dependencies'];
printTrace('Found plugin $name at $packageRootPath');
return Plugin.fromYaml(
name,
packageRootPath,
flutterConfig['plugin'] as YamlMap,
dependencies == null ? <String>[] : <String>[...dependencies.keys],
);
}

Expand All @@ -281,29 +309,58 @@ List<Plugin> findPlugins(FlutterProject project) {
return plugins;
}

/// Returns true if .flutter-plugins has changed, otherwise returns false.
/// Writes the .flutter-plugins and .flutter-plugins-dependencies files based on the list of plugins.
/// If there aren't any plugins, then the files aren't written to disk.
///
/// Finally, returns [true] if .flutter-plugins or .flutter-plugins-dependencies have changed,
/// otherwise returns [false].
bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
final List<dynamic> directAppDependencies = <dynamic>[];
final StringBuffer flutterPluginsBuffer = StringBuffer();

final Set<String> pluginNames = <String>{};
for (Plugin plugin in plugins) {
pluginNames.add(plugin.name);
}
for (Plugin plugin in plugins) {
flutterPluginsBuffer.write('${plugin.name}=${escapePath(plugin.path)}\n');
directAppDependencies.add(<String, dynamic>{
'name': plugin.name,
// Extract the plugin dependencies which happen to be plugins.
'dependencies': <String>[...plugin.dependencies.where(pluginNames.contains)],
});
}
final File pluginsFile = project.flutterPluginsFile;
final String oldContents = _readFlutterPluginsList(project);
final String pluginManifest =
plugins.map<String>((Plugin p) => '${p.name}=${escapePath(p.path)}').join('\n');
if (pluginManifest.isNotEmpty) {
pluginsFile.writeAsStringSync('$pluginManifest\n', flush: true);
final String oldPluginFileContent = _readFileContent(pluginsFile);
final String pluginFileContent = flutterPluginsBuffer.toString();
if (pluginFileContent.isNotEmpty) {
pluginsFile.writeAsStringSync(pluginFileContent, flush: true);
} else {
if (pluginsFile.existsSync()) {
pluginsFile.deleteSync();
}
}
final String newContents = _readFlutterPluginsList(project);
return oldContents != newContents;

final File dependenciesFile = project.flutterPluginsDependenciesFile;
final String oldDependenciesFileContent = _readFileContent(dependenciesFile);
final String dependenciesFileContent = json.encode(<String, dynamic>{
'dependencyGraph': directAppDependencies,
});
if (pluginFileContent.isNotEmpty) {
dependenciesFile.writeAsStringSync(dependenciesFileContent, flush: true);
} else {
if (dependenciesFile.existsSync()) {
dependenciesFile.deleteSync();
}
}

return oldPluginFileContent != _readFileContent(pluginsFile)
|| oldDependenciesFileContent != _readFileContent(dependenciesFile);
}

/// Returns the contents of the `.flutter-plugins` file in [project], or
/// null if that file does not exist.
String _readFlutterPluginsList(FlutterProject project) {
return project.flutterPluginsFile.existsSync()
? project.flutterPluginsFile.readAsStringSync()
: null;
/// Returns the contents of [File] or [null] if that file does not exist.
String _readFileContent(File file) {
return file.existsSync() ? file.readAsStringSync() : null;
}

const String _androidPluginRegistryTemplateOldEmbedding = '''package io.flutter.plugins;
Expand Down Expand Up @@ -782,5 +839,5 @@ Future<void> injectPlugins(FlutterProject project, {bool checkProjects = false})
///
/// Assumes [refreshPluginsList] has been called since last change to `pubspec.yaml`.
bool hasPlugins(FlutterProject project) {
return _readFlutterPluginsList(project) != null;
return _readFileContent(project.flutterPluginsFile) != null;
}
4 changes: 4 additions & 0 deletions packages/flutter_tools/lib/src/project.dart
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ class FlutterProject {
/// The `.flutter-plugins` file of this project.
File get flutterPluginsFile => directory.childFile('.flutter-plugins');

/// The `.flutter-plugins-dependencies` file of this project,
/// which contains the dependencies each plugin depends on.
File get flutterPluginsDependenciesFile => directory.childFile('.flutter-plugins-dependencies');

/// The `.dart-tool` directory of this project.
Directory get dartTool => directory.childDirectory('.dart_tool');

Expand Down
1 change: 1 addition & 0 deletions packages/flutter_tools/templates/app/.gitignore.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ build/
.android/
.ios/
.flutter-plugins
.flutter-plugins-dependencies
1 change: 1 addition & 0 deletions packages/flutter_tools/templates/package/.gitignore.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
Expand Down
Loading

0 comments on commit b6e9200

Please sign in to comment.