Revert "Revert "Use FlutterProject to locate files (#18913)" (#19409)"  (#19456)

With a fix of a path being printed relative instead of absolute.
diff --git a/packages/flutter_tools/lib/src/ios/cocoapods.dart b/packages/flutter_tools/lib/src/ios/cocoapods.dart
index 9904812..d6dc48c 100644
--- a/packages/flutter_tools/lib/src/ios/cocoapods.dart
+++ b/packages/flutter_tools/lib/src/ios/cocoapods.dart
@@ -15,8 +15,8 @@
 import '../base/process_manager.dart';
 import '../base/version.dart';
 import '../cache.dart';
-import '../flutter_manifest.dart';
 import '../globals.dart';
+import '../project.dart';
 import 'xcodeproj.dart';
 
 const String noCocoaPodsConsequence = '''
@@ -81,18 +81,18 @@
   Future<bool> get isCocoaPodsInitialized => fs.isDirectory(fs.path.join(homeDirPath, '.cocoapods', 'repos', 'master'));
 
   Future<bool> processPods({
-    @required Directory appIosDirectory,
+    @required IosProject iosProject,
     // For backward compatibility with previously created Podfile only.
     @required String iosEngineDir,
     bool isSwift = false,
     bool dependenciesChanged = true,
   }) async {
-    if (!(await appIosDirectory.childFile('Podfile').exists())) {
+    if (!(await iosProject.podfile.exists())) {
       throwToolExit('Podfile missing');
     }
     if (await _checkPodCondition()) {
-      if (_shouldRunPodInstall(appIosDirectory, dependenciesChanged)) {
-        await _runPodInstall(appIosDirectory, iosEngineDir);
+      if (_shouldRunPodInstall(iosProject, dependenciesChanged)) {
+        await _runPodInstall(iosProject, iosEngineDir);
         return true;
       }
     }
@@ -151,18 +151,18 @@
   /// Ensures the `ios` sub-project of the Flutter project at [appDirectory]
   /// contains a suitable `Podfile` and that its `Flutter/Xxx.xcconfig` files
   /// include pods configuration.
-  void setupPodfile(String appDirectory, FlutterManifest manifest) {
+  void setupPodfile(IosProject iosProject) {
     if (!xcodeProjectInterpreter.isInstalled) {
       // Don't do anything for iOS when host platform doesn't support it.
       return;
     }
-    if (!fs.directory(fs.path.join(appDirectory, 'ios')).existsSync()) {
+    if (!iosProject.directory.existsSync()) {
       return;
     }
-    final String podfilePath = fs.path.join(appDirectory, 'ios', 'Podfile');
-    if (!fs.file(podfilePath).existsSync()) {
+    final File podfile = iosProject.podfile;
+    if (!podfile.existsSync()) {
       final bool isSwift = xcodeProjectInterpreter.getBuildSettings(
-        fs.path.join(appDirectory, 'ios', 'Runner.xcodeproj'),
+        iosProject.directory.childFile('Runner.xcodeproj').path,
         'Runner',
       ).containsKey('SWIFT_VERSION');
       final File podfileTemplate = fs.file(fs.path.join(
@@ -173,15 +173,14 @@
         'cocoapods',
         isSwift ? 'Podfile-swift' : 'Podfile-objc',
       ));
-      podfileTemplate.copySync(podfilePath);
+      podfileTemplate.copySync(podfile.path);
     }
-
-    _addPodsDependencyToFlutterXcconfig(appDirectory, 'Debug');
-    _addPodsDependencyToFlutterXcconfig(appDirectory, 'Release');
+    _addPodsDependencyToFlutterXcconfig(iosProject, 'Debug');
+    _addPodsDependencyToFlutterXcconfig(iosProject, 'Release');
   }
 
-  void _addPodsDependencyToFlutterXcconfig(String appDirectory, String mode) {
-    final File file = fs.file(fs.path.join(appDirectory, 'ios', 'Flutter', '$mode.xcconfig'));
+  void _addPodsDependencyToFlutterXcconfig(IosProject iosProject, String mode) {
+    final File file = iosProject.xcodeConfigFor(mode);
     if (file.existsSync()) {
       final String content = file.readAsStringSync();
       final String include = '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.${mode
@@ -192,12 +191,11 @@
   }
 
   /// Ensures that pod install is deemed needed on next check.
-  void invalidatePodInstallOutput(String appDirectory) {
-    final File manifest = fs.file(
-      fs.path.join(appDirectory, 'ios', 'Pods', 'Manifest.lock'),
-    );
-    if (manifest.existsSync())
-      manifest.deleteSync();
+  void invalidatePodInstallOutput(IosProject iosProject) {
+    final File manifestLock = iosProject.podManifestLock;
+    if (manifestLock.existsSync()) {
+      manifestLock.deleteSync();
+    }
   }
 
   // Check if you need to run pod install.
@@ -206,24 +204,25 @@
   // 2. Podfile.lock doesn't exist or is older than Podfile
   // 3. Pods/Manifest.lock doesn't exist (It is deleted when plugins change)
   // 4. Podfile.lock doesn't match Pods/Manifest.lock.
-  bool _shouldRunPodInstall(Directory appIosDirectory, bool dependenciesChanged) {
+  bool _shouldRunPodInstall(IosProject iosProject, bool dependenciesChanged) {
     if (dependenciesChanged)
       return true;
-    final File podfileFile = appIosDirectory.childFile('Podfile');
-    final File podfileLockFile = appIosDirectory.childFile('Podfile.lock');
-    final File manifestLockFile =
-        appIosDirectory.childFile(fs.path.join('Pods', 'Manifest.lock'));
+
+    final File podfileFile = iosProject.podfile;
+    final File podfileLockFile = iosProject.podfileLock;
+    final File manifestLockFile = iosProject.podManifestLock;
+
     return !podfileLockFile.existsSync()
         || !manifestLockFile.existsSync()
         || podfileLockFile.statSync().modified.isBefore(podfileFile.statSync().modified)
         || podfileLockFile.readAsStringSync() != manifestLockFile.readAsStringSync();
   }
 
-  Future<Null> _runPodInstall(Directory appIosDirectory, String engineDirectory) async {
+  Future<Null> _runPodInstall(IosProject iosProject, String engineDirectory) async {
     final Status status = logger.startProgress('Running pod install...', expectSlowOperation: true);
     final ProcessResult result = await processManager.run(
       <String>['pod', 'install', '--verbose'],
-      workingDirectory: appIosDirectory.path,
+      workingDirectory: iosProject.directory.path,
       environment: <String, String>{
         // For backward compatibility with previously created Podfile only.
         'FLUTTER_FRAMEWORK_DIR': engineDirectory,
@@ -244,7 +243,7 @@
       }
     }
     if (result.exitCode != 0) {
-      invalidatePodInstallOutput(appIosDirectory.parent.path);
+      invalidatePodInstallOutput(iosProject);
       _diagnosePodInstallFailure(result);
       throwToolExit('Error running pod install');
     }
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index 85d4d87..63c8da9 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -20,9 +20,9 @@
 import '../base/process_manager.dart';
 import '../base/utils.dart';
 import '../build_info.dart';
-import '../flutter_manifest.dart';
 import '../globals.dart';
 import '../plugins.dart';
+import '../project.dart';
 import '../services.dart';
 import 'cocoapods.dart';
 import 'code_signing.dart';
@@ -233,18 +233,15 @@
   final Directory appDirectory = fs.directory(app.appDirectory);
   await _addServicesToBundle(appDirectory);
 
-  final FlutterManifest manifest = await FlutterManifest.createFromPath(
-    fs.currentDirectory.childFile('pubspec.yaml').path,
-  );
-  updateGeneratedXcodeProperties(
-    projectPath: fs.currentDirectory.path,
-    buildInfo: buildInfo,
+  final FlutterProject project = new FlutterProject(fs.currentDirectory);
+  await updateGeneratedXcodeProperties(
+    project: project,
     targetOverride: targetOverride,
     previewDart2: buildInfo.previewDart2,
-    manifest: manifest,
+    buildInfo: buildInfo,
   );
 
-  if (hasPlugins()) {
+  if (hasPlugins(project)) {
     final String iosPath = fs.path.join(fs.currentDirectory.path, app.appDirectory);
     // If the Xcode project, Podfile, or Generated.xcconfig have changed since
     // last run, pods should be updated.
@@ -258,7 +255,7 @@
       properties: <String, String>{},
     );
     final bool didPodInstall = await cocoaPods.processPods(
-      appIosDirectory: appDirectory,
+      iosProject: project.ios,
       iosEngineDir: flutterFrameworkDir(buildInfo.mode),
       isSwift: app.isSwift,
       dependenciesChanged: !await fingerprinter.doesFingerprintMatch()
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
index b9bf73d..4f7f6b5 100644
--- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart
+++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -2,6 +2,8 @@
 // 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:meta/meta.dart';
 
 import '../artifacts.dart';
@@ -17,6 +19,7 @@
 import '../cache.dart';
 import '../flutter_manifest.dart';
 import '../globals.dart';
+import '../project.dart';
 
 final RegExp _settingExpr = new RegExp(r'(\w+)\s*=\s*(.*)$');
 final RegExp _varExpr = new RegExp(r'\$\((.*)\)');
@@ -25,27 +28,18 @@
   return fs.path.normalize(fs.path.dirname(artifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, mode)));
 }
 
-String _generatedXcodePropertiesPath({@required String projectPath, @required FlutterManifest manifest}) {
-  if (manifest.isModule) {
-    return fs.path.join(projectPath, '.ios', 'Flutter', 'Generated.xcconfig');
-  } else {
-    return fs.path.join(projectPath, 'ios', 'Flutter', 'Generated.xcconfig');
-  }
-}
-
 /// Writes default Xcode properties files in the Flutter project at [projectPath],
 /// if project is an iOS project and such files are out of date or do not
 /// already exist.
-void generateXcodeProperties({String projectPath, FlutterManifest manifest}) {
-  if (manifest.isModule || fs.isDirectorySync(fs.path.join(projectPath, 'ios'))) {
-    final File propertiesFile = fs.file(_generatedXcodePropertiesPath(projectPath: projectPath, manifest: manifest));
-    if (!Cache.instance.fileOlderThanToolsStamp(propertiesFile)) {
+Future<void> generateXcodeProperties({FlutterProject project}) async {
+  if ((await project.manifest).isModule ||
+      project.ios.directory.existsSync()) {
+    if (!Cache.instance.fileOlderThanToolsStamp(await project.generatedXcodePropertiesFile)) {
       return;
     }
 
-    updateGeneratedXcodeProperties(
-      projectPath: projectPath,
-      manifest: manifest,
+    await updateGeneratedXcodeProperties(
+      project: project,
       buildInfo: BuildInfo.debug,
       targetOverride: bundle.defaultMainPath,
       previewDart2: true,
@@ -57,13 +51,12 @@
 ///
 /// targetOverride: Optional parameter, if null or unspecified the default value
 /// from xcode_backend.sh is used 'lib/main.dart'.
-void updateGeneratedXcodeProperties({
-  @required String projectPath,
-  @required FlutterManifest manifest,
+Future<void> updateGeneratedXcodeProperties({
+  @required FlutterProject project,
   @required BuildInfo buildInfo,
   String targetOverride,
   @required bool previewDart2,
-}) {
+}) async {
   final StringBuffer localsBuffer = new StringBuffer();
 
   localsBuffer.writeln('// This is a generated file; do not edit or check into version control.');
@@ -72,7 +65,7 @@
   localsBuffer.writeln('FLUTTER_ROOT=$flutterRoot');
 
   // This holds because requiresProjectRoot is true for this command
-  localsBuffer.writeln('FLUTTER_APPLICATION_PATH=${fs.path.normalize(projectPath)}');
+  localsBuffer.writeln('FLUTTER_APPLICATION_PATH=${fs.path.normalize(project.directory.path)}');
 
   // Relative to FLUTTER_APPLICATION_PATH, which is [Directory.current].
   if (targetOverride != null)
@@ -86,6 +79,7 @@
 
   localsBuffer.writeln('SYMROOT=\${SOURCE_ROOT}/../${getIosBuildDirectory()}');
 
+  final FlutterManifest manifest = await project.manifest;
   if (!manifest.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
@@ -125,9 +119,9 @@
     localsBuffer.writeln('TRACK_WIDGET_CREATION=true');
   }
 
-  final File localsFile = fs.file(_generatedXcodePropertiesPath(projectPath: projectPath, manifest: manifest));
-  localsFile.createSync(recursive: true);
-  localsFile.writeAsStringSync(localsBuffer.toString());
+  final File generatedXcodePropertiesFile = await project.generatedXcodePropertiesFile;
+  generatedXcodePropertiesFile.createSync(recursive: true);
+  generatedXcodePropertiesFile.writeAsStringSync(localsBuffer.toString());
 }
 
 XcodeProjectInterpreter get xcodeProjectInterpreter => context[XcodeProjectInterpreter];