add version to pubspec.yaml (#16857)

Uses the `version` property from the `pubspec.yaml` file to set the corresponding fields in the `local.properties` file respectively in the `Generated.xcconfig` file.

The `--build-name` and `--build-number` options have changed. Now they trump the `version` property from the `pubspec.yaml` file.

If the `version` property is not set and the  `--build-name` and `--build-number` options are not provided, the build command will not change the `local.properties` / `Generated.xcconfig` file.
diff --git a/packages/flutter_tools/lib/src/flutter_manifest.dart b/packages/flutter_tools/lib/src/flutter_manifest.dart
index 0c26c47..c151839 100644
--- a/packages/flutter_tools/lib/src/flutter_manifest.dart
+++ b/packages/flutter_tools/lib/src/flutter_manifest.dart
@@ -13,6 +13,8 @@
 import 'cache.dart';
 import 'globals.dart';
 
+final RegExp _versionPattern = new RegExp(r'^(\d+)(\.(\d+)(\.(\d+))?)?(\+(\d+))?$');
+
 /// A wrapper around the `flutter` section in the `pubspec.yaml` file.
 class FlutterManifest {
   FlutterManifest._();
@@ -51,6 +53,36 @@
 
   String get appName => _descriptor['name'] ?? '';
 
+  /// The version String from the `pubspec.yaml` file.
+  /// Can be null if it isn't set or has a wrong format.
+  String get appVersion {
+    final String version = _descriptor['version']?.toString();
+    if (version != null && _versionPattern.hasMatch(version))
+      return version;
+    else
+      return null;
+  }
+
+  /// The build version name from the `pubspec.yaml` file.
+  /// Can be null if version isn't set or has a wrong format.
+  String get buildName {
+    if (appVersion != null && appVersion.contains('+'))
+      return appVersion.split('+')?.elementAt(0);
+    else
+      return appVersion;
+  }
+
+  /// The build version number from the `pubspec.yaml` file.
+  /// Can be null if version isn't set or has a wrong format.
+  int get buildNumber {
+    if (appVersion != null && appVersion.contains('+')) {
+      final String value = appVersion.split('+')?.elementAt(1);
+      return value == null ? null : int.tryParse(value);
+    } else {
+      return null;
+    }
+  }
+
   bool get usesMaterialDesign {
     return _flutterDescriptor['uses-material-design'] ?? false;
   }