Unverified Commit a737c86a authored by Mikkel Nygaard Ravn's avatar Mikkel Nygaard Ravn Committed by GitHub

Avoid null manifests in FlutterProject (#20332)

parent 142cbae7
......@@ -203,18 +203,13 @@ distributionUrl=https\\://services.gradle.org/distributions/gradle-$gradleVersio
/// Overwrite local.properties in the specified Flutter project's Android
/// sub-project, if needed.
///
/// Throws tool exit, if `pubspec.yaml` is invalid.
///
/// If [requireSdk] is `true` this will fail with a tool exit if no Android Sdk
/// is found.
/// If [requireAndroidSdk] is true (the default) and no Android SDK is found,
/// this will fail with a [ToolExit].
Future<void> updateLocalProperties({
@required FlutterProject project,
BuildInfo buildInfo,
bool requireAndroidSdk = true,
}) async {
if (project.manifest == null) {
throwToolExit('Invalid `pubspec.yaml`');
}
if (requireAndroidSdk && androidSdk == null) {
throwToolExit('Unable to locate Android SDK. Please run `flutter doctor` for more details.');
}
......
......@@ -28,14 +28,6 @@ class FlutterManifest {
return manifest;
}
/// Returns a mock manifest with the given contents.
static FlutterManifest mock(Map<String, dynamic> contents) {
final FlutterManifest manifest = new FlutterManifest._();
manifest._descriptor = contents ?? const <String, dynamic>{};
manifest._flutterDescriptor = manifest._descriptor['flutter'] ?? const <String, dynamic>{};
return manifest;
}
/// Returns null on invalid manifest. Returns empty manifest on missing file.
static Future<FlutterManifest> createFromPath(String path) async {
if (path == null || !fs.isFileSync(path))
......@@ -78,8 +70,10 @@ class FlutterManifest {
/// A map representation of the `flutter` section in the `pubspec.yaml` file.
Map<String, dynamic> _flutterDescriptor;
/// True if the `pubspec.yaml` file does not exist.
bool get isEmpty => _descriptor.isEmpty;
/// The string value of the top-level `name` property in the `pubspec.yaml` file.
String get appName => _descriptor['name'] ?? '';
/// The version String from the `pubspec.yaml` file.
......
......@@ -16,7 +16,6 @@ import '../base/process_manager.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../cache.dart';
import '../flutter_manifest.dart';
import '../globals.dart';
import '../project.dart';
......@@ -59,20 +58,19 @@ Future<void> updateGeneratedXcodeProperties({
localsBuffer.writeln('SYMROOT=\${SOURCE_ROOT}/../${getIosBuildDirectory()}');
final FlutterManifest manifest = project.manifest;
if (!manifest.isModule) {
if (!project.isModule) {
// For module projects we do not want to write the FLUTTER_FRAMEWORK_DIR
// explicitly. Rather we rely on the xcode backend script and the Podfile
// logic to derive it from FLUTTER_ROOT and FLUTTER_BUILD_MODE.
localsBuffer.writeln('FLUTTER_FRAMEWORK_DIR=${flutterFrameworkDir(buildInfo.mode)}');
}
final String buildName = buildInfo?.buildName ?? manifest.buildName;
final String buildName = buildInfo?.buildName ?? project.manifest.buildName;
if (buildName != null) {
localsBuffer.writeln('FLUTTER_BUILD_NAME=$buildName');
}
final int buildNumber = buildInfo?.buildNumber ?? manifest.buildNumber;
final int buildNumber = buildInfo?.buildNumber ?? project.manifest.buildNumber;
if (buildNumber != null) {
localsBuffer.writeln('FLUTTER_BUILD_NUMBER=$buildNumber');
}
......
......@@ -8,6 +8,7 @@ import 'dart:convert';
import 'package:meta/meta.dart';
import 'android/gradle.dart' as gradle;
import 'base/common.dart';
import 'base/file_system.dart';
import 'build_info.dart';
import 'bundle.dart' as bundle;
......@@ -28,34 +29,39 @@ import 'template.dart';
/// cached.
class FlutterProject {
@visibleForTesting
FlutterProject(this.directory, this.manifest, this._exampleManifest);
FlutterProject(this.directory, this.manifest, this._exampleManifest)
: assert(directory != null),
assert(manifest != null),
assert(_exampleManifest != null);
/// Returns a future that completes with a FlutterProject view of the given directory.
/// Returns a future that completes with a [FlutterProject] view of the given directory
/// or a ToolExit error, if `pubspec.yaml` or `example/pubspec.yaml` is invalid.
static Future<FlutterProject> fromDirectory(Directory directory) async {
final FlutterManifest manifest = await FlutterManifest.createFromPath(
assert(directory != null);
final FlutterManifest manifest = await _readManifest(
directory.childFile(bundle.defaultManifestPath).path,
);
final Directory exampleDirectory = _exampleDirectory(directory);
final FlutterManifest exampleManifest = await FlutterManifest.createFromPath(
exampleDirectory.childFile(bundle.defaultManifestPath).path,
final FlutterManifest exampleManifest = await _readManifest(
_exampleDirectory(directory).childFile(bundle.defaultManifestPath).path,
);
return new FlutterProject(directory, manifest, exampleManifest);
}
/// Returns a future that completes with a FlutterProject view of the current directory.
/// Returns a future that completes with a [FlutterProject] view of the current directory.
/// or a ToolExit error, if `pubspec.yaml` or `example/pubspec.yaml` is invalid.
static Future<FlutterProject> current() => fromDirectory(fs.currentDirectory);
/// Returns a future that completes with a FlutterProject view of the given directory.
/// Returns a future that completes with a [FlutterProject] view of the given directory.
/// or a ToolExit error, if `pubspec.yaml` or `example/pubspec.yaml` is invalid.
static Future<FlutterProject> fromPath(String path) => fromDirectory(fs.directory(path));
/// The location of this project.
final Directory directory;
/// The manifest of this project, or null, if `pubspec.yaml` is invalid.
/// The manifest of this project.
final FlutterManifest manifest;
/// The manifest of the example sub-project of this project, or null, if
/// `example/pubspec.yaml` is invalid.
/// The manifest of the example sub-project of this project.
final FlutterManifest _exampleManifest;
/// Asynchronously returns the organization names found in this project as
......@@ -96,7 +102,8 @@ class FlutterProject {
FlutterManifest.empty(),
);
bool get isModule => manifest != null && manifest.isModule;
/// True, if this project is a Flutter module.
bool get isModule => manifest.isModule;
/// True, if this project has an example application.
bool get hasExampleApp => _exampleDirectory(directory).existsSync();
......@@ -104,6 +111,18 @@ class FlutterProject {
/// The directory that will contain the example if an example exists.
static Directory _exampleDirectory(Directory directory) => directory.childDirectory('example');
/// Reads and validates the `pubspec.yaml` file at [path], asynchronously
/// returning a [FlutterManifest] representation of the contents.
///
/// Completes with an empty [FlutterManifest], if the file does not exist.
/// Completes with a ToolExit on validation error.
static Future<FlutterManifest> _readManifest(String path) async {
final FlutterManifest manifest = await FlutterManifest.createFromPath(path);
if (manifest == null)
throwToolExit('Please correct the pubspec.yaml file at $path');
return manifest;
}
/// Generates project files necessary to make Gradle builds work on Android
/// and CocoaPods+Xcode work on iOS, for app and module projects only.
Future<void> ensureReadyForPlatformSpecificTooling() 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