| // Copyright 2015 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:yaml/yaml.dart'; |
| |
| import 'android/android_sdk.dart'; |
| import 'base/file_system.dart'; |
| import 'convert.dart'; |
| import 'dart/package_map.dart'; |
| import 'globals.dart'; |
| |
| const String _kFlutterManifestPath = 'pubspec.yaml'; |
| const String _kFlutterServicesManifestPath = 'flutter_services.yaml'; |
| |
| dynamic _loadYamlFile(String path) { |
| printTrace("Looking for YAML at '$path'"); |
| if (!fs.isFileSync(path)) |
| return null; |
| final String manifestString = fs.file(path).readAsStringSync(); |
| return loadYaml(manifestString); |
| } |
| |
| /// Loads all services specified in `pubspec.yaml`. Parses each service config file, |
| /// storing meta data in [services] and the list of jar files in [jars]. |
| Future<void> parseServiceConfigs( |
| List<Map<String, String>> services, { |
| List<File> jars, |
| }) async { |
| Map<String, Uri> packageMap; |
| try { |
| packageMap = PackageMap(PackageMap.globalPackagesPath).map; |
| } on FormatException catch (error) { |
| printTrace('Invalid ".packages" file while parsing service configs:\n$error'); |
| return; |
| } |
| |
| dynamic manifest; |
| try { |
| manifest = _loadYamlFile(_kFlutterManifestPath); |
| manifest = manifest['flutter']; |
| } catch (error) { |
| printStatus('Error detected in pubspec.yaml:', emphasis: true); |
| printError('$error'); |
| return; |
| } |
| if (manifest == null || manifest['services'] == null) { |
| printTrace('No services specified in the manifest'); |
| return; |
| } |
| |
| for (String service in manifest['services']) { |
| final String serviceRoot = packageMap[service].path; |
| final dynamic serviceConfig = _loadYamlFile('$serviceRoot/$_kFlutterServicesManifestPath'); |
| if (serviceConfig == null) { |
| printStatus('No $_kFlutterServicesManifestPath found for service "$serviceRoot"; skipping.'); |
| continue; |
| } |
| |
| for (Map<String, String> service in serviceConfig['services']) { |
| services.add(<String, String>{ |
| 'root': serviceRoot, |
| 'name': service['name'], |
| 'android-class': service['android-class'], |
| 'ios-framework': service['ios-framework'], |
| }); |
| } |
| |
| if (jars != null && serviceConfig['jars'] is Iterable) { |
| for (String jar in serviceConfig['jars']) |
| jars.add(fs.file(await getServiceFromUrl(jar, serviceRoot, service))); |
| } |
| } |
| } |
| |
| Future<String> getServiceFromUrl(String url, String rootDir, String serviceName) async { |
| if (url.startsWith('android-sdk:') && androidSdk != null) { |
| // It's something shipped in the standard android SDK. |
| return url.replaceAll('android-sdk:', '${androidSdk.directory}/'); |
| } else if (url.startsWith('http:') || url.startsWith('https:')) { |
| // It's a regular file to download. |
| return await cache.getThirdPartyFile(url, serviceName); |
| } else { |
| // Assume url is a path relative to the service's root dir. |
| return fs.path.join(rootDir, url); |
| } |
| } |
| |
| /// Outputs a services.json file for the flutter engine to read. Format: |
| /// { |
| /// services: [ |
| /// { name: string, framework: string }, |
| /// ... |
| /// ] |
| /// } |
| File generateServiceDefinitions( |
| String dir, |
| List<Map<String, String>> servicesIn, |
| ) { |
| final List<Map<String, String>> services = |
| servicesIn.map<Map<String, String>>((Map<String, String> service) => <String, String>{ |
| 'name': service['name'], |
| 'class': service['android-class'], |
| }).toList(); |
| |
| final Map<String, dynamic> jsonObject = <String, dynamic>{'services': services}; |
| final File servicesFile = fs.file(fs.path.join(dir, 'services.json')); |
| servicesFile.writeAsStringSync(json.encode(jsonObject), mode: FileMode.write, flush: true); |
| return servicesFile; |
| } |