refactor cocoapods validator to detect broken install (#38560)

diff --git a/packages/flutter_tools/lib/src/base/user_messages.dart b/packages/flutter_tools/lib/src/base/user_messages.dart
index 1764483..a1f1d91 100644
--- a/packages/flutter_tools/lib/src/base/user_messages.dart
+++ b/packages/flutter_tools/lib/src/base/user_messages.dart
@@ -172,6 +172,11 @@
       '$consequence\n'
       'To upgrade:\n'
       '$upgradeInstructions';
+  String cocoaPodsBrokenInstall(String consequence, String reinstallInstructions) =>
+      'CocoaPods installed but not working.\n'
+      '$consequence\n'
+      'To re-install CocoaPods, run:\n'
+      '$reinstallInstructions';
 
   // Messages used in VsCodeValidator
   String vsCodeVersion(String version) => 'version $version';
diff --git a/packages/flutter_tools/lib/src/macos/cocoapods.dart b/packages/flutter_tools/lib/src/macos/cocoapods.dart
index ca2577f..ac006fa 100644
--- a/packages/flutter_tools/lib/src/macos/cocoapods.dart
+++ b/packages/flutter_tools/lib/src/macos/cocoapods.dart
@@ -29,6 +29,11 @@
   Flutter is unable to determine the installed CocoaPods's version.
   Ensure that the output of 'pod --version' contains only digits and . to be recognized by Flutter.''';
 
+const String brokenCocoaPodsConsequence = '''
+  You appear to have CocoaPods installed but it is not working.
+  This can happen if the version of Ruby that CocoaPods was installed with is different from the one being used to invoke it.
+  This can usually be fixed by re-installing CocoaPods. For more info, see https://github.com/flutter/flutter/issues/14293.''';
+
 const String cocoaPodsInstallInstructions = '''
   sudo gem install cocoapods
   pod setup''';
@@ -52,6 +57,8 @@
   belowRecommendedVersion,
   /// Everything should be fine.
   recommended,
+  /// iOS plugins will not work, re-install required.
+  brokenInstall,
 }
 
 class CocoaPods {
@@ -60,6 +67,8 @@
   String get cocoaPodsMinimumVersion => '1.6.0';
   String get cocoaPodsRecommendedVersion => '1.6.0';
 
+  Future<bool> get isInstalled => exitsHappyAsync(<String>['which', 'pod']);
+
   Future<String> get cocoaPodsVersionText {
     _versionText ??= runAsync(<String>['pod', '--version']).then<String>((RunResult result) {
       return result.exitCode == 0 ? result.stdout.trim() : null;
@@ -68,9 +77,13 @@
   }
 
   Future<CocoaPodsStatus> get evaluateCocoaPodsInstallation async {
-    final String versionText = await cocoaPodsVersionText;
-    if (versionText == null)
+    if (!(await isInstalled)) {
       return CocoaPodsStatus.notInstalled;
+    }
+    final String versionText = await cocoaPodsVersionText;
+    if (versionText == null) {
+      return CocoaPodsStatus.brokenInstall;
+    }
     try {
       final Version installedVersion = Version.parse(versionText);
       if (installedVersion == null)
diff --git a/packages/flutter_tools/lib/src/macos/cocoapods_validator.dart b/packages/flutter_tools/lib/src/macos/cocoapods_validator.dart
index aaee745..ce57632 100644
--- a/packages/flutter_tools/lib/src/macos/cocoapods_validator.dart
+++ b/packages/flutter_tools/lib/src/macos/cocoapods_validator.dart
@@ -34,6 +34,11 @@
         status = ValidationType.missing;
         messages.add(ValidationMessage.error(
             userMessages.cocoaPodsMissing(noCocoaPodsConsequence, cocoaPodsInstallInstructions)));
+      } else if (cocoaPodsStatus == CocoaPodsStatus.brokenInstall) {
+        status = ValidationType.missing;
+        messages.add(ValidationMessage.error(
+            userMessages.cocoaPodsBrokenInstall(brokenCocoaPodsConsequence, cocoaPodsInstallInstructions)));
+
       } else if (cocoaPodsStatus == CocoaPodsStatus.unknownVersion) {
         status = ValidationType.partial;
         messages.add(ValidationMessage.hint(