mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
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.
This commit is contained in:
parent
f986048094
commit
c65e9d19a4
@ -3,9 +3,6 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
|
||||||
|
|
||||||
import '../android/android_sdk.dart';
|
import '../android/android_sdk.dart';
|
||||||
import '../artifacts.dart';
|
import '../artifacts.dart';
|
||||||
@ -17,7 +14,9 @@ import '../base/platform.dart';
|
|||||||
import '../base/process.dart';
|
import '../base/process.dart';
|
||||||
import '../base/utils.dart';
|
import '../base/utils.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
|
import '../bundle.dart' as bundle;
|
||||||
import '../cache.dart';
|
import '../cache.dart';
|
||||||
|
import '../flutter_manifest.dart';
|
||||||
import '../globals.dart';
|
import '../globals.dart';
|
||||||
import 'android_sdk.dart';
|
import 'android_sdk.dart';
|
||||||
import 'android_studio.dart';
|
import 'android_studio.dart';
|
||||||
@ -95,7 +94,7 @@ Future<GradleProject> _gradleProject() async {
|
|||||||
// of calculating the app properties using Gradle. This may take minutes.
|
// of calculating the app properties using Gradle. This may take minutes.
|
||||||
Future<GradleProject> _readGradleProject() async {
|
Future<GradleProject> _readGradleProject() async {
|
||||||
final String gradle = await _ensureGradle();
|
final String gradle = await _ensureGradle();
|
||||||
updateLocalProperties();
|
await updateLocalProperties();
|
||||||
try {
|
try {
|
||||||
final Status status = logger.startProgress('Resolving dependencies...', expectSlowOperation: true);
|
final Status status = logger.startProgress('Resolving dependencies...', expectSlowOperation: true);
|
||||||
final RunResult runResult = await runCheckedAsync(
|
final RunResult runResult = await runCheckedAsync(
|
||||||
@ -198,10 +197,13 @@ distributionUrl=https\\://services.gradle.org/distributions/gradle-$gradleVersio
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create android/local.properties if needed, and update Flutter settings.
|
/// Create android/local.properties if needed, and update Flutter settings.
|
||||||
void updateLocalProperties({String projectPath, BuildInfo buildInfo}) {
|
Future<void> updateLocalProperties({String projectPath, BuildInfo buildInfo}) async {
|
||||||
final File localProperties = (projectPath == null)
|
final File localProperties = (projectPath == null)
|
||||||
? fs.file(fs.path.join('android', 'local.properties'))
|
? fs.file(fs.path.join('android', 'local.properties'))
|
||||||
: fs.file(fs.path.join(projectPath, 'android', 'local.properties'));
|
: fs.file(fs.path.join(projectPath, 'android', 'local.properties'));
|
||||||
|
final String flutterManifest = (projectPath == null)
|
||||||
|
? fs.path.join(bundle.defaultManifestPath)
|
||||||
|
: fs.path.join(projectPath, bundle.defaultManifestPath);
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
SettingsFile settings;
|
SettingsFile settings;
|
||||||
@ -225,85 +227,39 @@ void updateLocalProperties({String projectPath, BuildInfo buildInfo}) {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlutterManifest manifest;
|
||||||
|
try {
|
||||||
|
manifest = await FlutterManifest.createFromPath(flutterManifest);
|
||||||
|
} catch (error) {
|
||||||
|
throwToolExit('Failed to load pubspec.yaml: $error');
|
||||||
|
}
|
||||||
|
|
||||||
|
final String buildName = buildInfo?.buildName ?? manifest.buildName;
|
||||||
|
if (buildName != null) {
|
||||||
|
settings.values['flutter.versionName'] = buildName;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int buildNumber = buildInfo?.buildNumber ?? manifest.buildNumber;
|
||||||
|
if (buildNumber != null) {
|
||||||
|
settings.values['flutter.versionCode'] = '$buildNumber';
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
settings.writeContents(localProperties);
|
settings.writeContents(localProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Null> findAndReplaceVersionProperties({@required BuildInfo buildInfo}) {
|
|
||||||
assert(buildInfo != null, 'buildInfo can\'t be null');
|
|
||||||
final Completer<Null> completer = new Completer<Null>();
|
|
||||||
|
|
||||||
// early return, if nothing has to be changed
|
|
||||||
if (buildInfo.buildNumber == null && buildInfo.buildName == null) {
|
|
||||||
completer.complete();
|
|
||||||
return completer.future;
|
|
||||||
}
|
|
||||||
|
|
||||||
final File appGradle = fs.file(fs.path.join('android', 'app', 'build.gradle'));
|
|
||||||
final File appGradleTmp = fs.file(fs.path.join('android', 'app', 'build.gradle.tmp'));
|
|
||||||
appGradleTmp.createSync();
|
|
||||||
|
|
||||||
if (appGradle.existsSync() && appGradleTmp.existsSync()) {
|
|
||||||
final Stream<List<int>> inputStream = appGradle.openRead();
|
|
||||||
final IOSink sink = appGradleTmp.openWrite();
|
|
||||||
|
|
||||||
inputStream.transform(utf8.decoder)
|
|
||||||
.transform(const LineSplitter())
|
|
||||||
.map((String line) {
|
|
||||||
|
|
||||||
// find and replace build number
|
|
||||||
if (buildInfo.buildNumber != null) {
|
|
||||||
if (line.contains(new RegExp(r'^[ |\t]*(versionCode)[ =\t]*\d*'))) {
|
|
||||||
return line.splitMapJoin(new RegExp(r'(versionCode)[ =\t]*\d*'), onMatch: (Match m) {
|
|
||||||
return 'versionCode ${buildInfo.buildNumber}';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// find and replace build name
|
|
||||||
if (buildInfo.buildName != null) {
|
|
||||||
if (line.contains(new RegExp(r'^[ |\t]*(versionName)[ =\t]*\"[0-9.]*"'))) {
|
|
||||||
return line.splitMapJoin(new RegExp(r'(versionName)[ =\t]*\"[0-9.]*"'), onMatch: (Match m) {
|
|
||||||
return 'versionName "${buildInfo.buildName}"';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return line;
|
|
||||||
})
|
|
||||||
.listen((String line) {
|
|
||||||
sink.writeln(line);
|
|
||||||
},
|
|
||||||
onDone: () {
|
|
||||||
sink.close();
|
|
||||||
try {
|
|
||||||
final File gradleOld = appGradle.renameSync(fs.path.join('android', 'app', 'build.gradle.old'));
|
|
||||||
appGradleTmp.renameSync(fs.path.join('android', 'app', 'build.gradle'));
|
|
||||||
gradleOld.deleteSync();
|
|
||||||
completer.complete();
|
|
||||||
} catch (error) {
|
|
||||||
printError('Failed to change version properties. $error');
|
|
||||||
completer.completeError('Failed to change version properties. $error');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onError: (dynamic error, StackTrace stack) {
|
|
||||||
printError('Failed to change version properties. ${error.toString()}');
|
|
||||||
sink.close();
|
|
||||||
appGradleTmp.deleteSync();
|
|
||||||
completer.completeError('Failed to change version properties. ${error.toString()}', stack);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return completer.future;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Null> buildGradleProject(BuildInfo buildInfo, String target) async {
|
Future<Null> buildGradleProject(BuildInfo buildInfo, String target) async {
|
||||||
// Update the local.properties file with the build mode.
|
// Update the local.properties file with the build mode, version name and code.
|
||||||
// FlutterPlugin v1 reads local.properties to determine build mode. Plugin v2
|
// FlutterPlugin v1 reads local.properties to determine build mode. Plugin v2
|
||||||
// uses the standard Android way to determine what to build, but we still
|
// uses the standard Android way to determine what to build, but we still
|
||||||
// update local.properties, in case we want to use it in the future.
|
// update local.properties, in case we want to use it in the future.
|
||||||
updateLocalProperties(buildInfo: buildInfo);
|
// Version name and number are provided by the pubspec.yaml file
|
||||||
await findAndReplaceVersionProperties(buildInfo: buildInfo);
|
// and can be overwritten with flutter build command.
|
||||||
|
// The default Gradle script reads the version name and number
|
||||||
|
// from the local.properties file.
|
||||||
|
await updateLocalProperties(buildInfo: buildInfo);
|
||||||
|
|
||||||
final String gradle = await _ensureGradle();
|
final String gradle = await _ensureGradle();
|
||||||
|
|
||||||
|
@ -289,11 +289,11 @@ To edit platform code in an IDE see https://flutter.io/platform-plugins/#edit-co
|
|||||||
|
|
||||||
if (argResults['pub']) {
|
if (argResults['pub']) {
|
||||||
await pubGet(context: PubContext.create, directory: appPath, offline: argResults['offline']);
|
await pubGet(context: PubContext.create, directory: appPath, offline: argResults['offline']);
|
||||||
new FlutterProject(fs.directory(appPath)).ensureReadyForPlatformSpecificTooling();
|
await new FlutterProject(fs.directory(appPath)).ensureReadyForPlatformSpecificTooling();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (android_sdk.androidSdk != null)
|
if (android_sdk.androidSdk != null)
|
||||||
gradle.updateLocalProperties(projectPath: appPath);
|
await gradle.updateLocalProperties(projectPath: appPath);
|
||||||
|
|
||||||
return generatedCount;
|
return generatedCount;
|
||||||
}
|
}
|
||||||
|
@ -82,13 +82,13 @@ class PackagesGetCommand extends FlutterCommand {
|
|||||||
|
|
||||||
await _runPubGet(target);
|
await _runPubGet(target);
|
||||||
final FlutterProject rootProject = new FlutterProject(fs.directory(target));
|
final FlutterProject rootProject = new FlutterProject(fs.directory(target));
|
||||||
rootProject.ensureReadyForPlatformSpecificTooling();
|
await rootProject.ensureReadyForPlatformSpecificTooling();
|
||||||
|
|
||||||
// Get/upgrade packages in example app as well
|
// Get/upgrade packages in example app as well
|
||||||
if (rootProject.hasExampleApp) {
|
if (rootProject.hasExampleApp) {
|
||||||
final FlutterProject exampleProject = rootProject.example;
|
final FlutterProject exampleProject = rootProject.example;
|
||||||
await _runPubGet(exampleProject.directory.path);
|
await _runPubGet(exampleProject.directory.path);
|
||||||
exampleProject.ensureReadyForPlatformSpecificTooling();
|
await exampleProject.ensureReadyForPlatformSpecificTooling();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ import 'base/file_system.dart';
|
|||||||
import 'cache.dart';
|
import 'cache.dart';
|
||||||
import 'globals.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.
|
/// A wrapper around the `flutter` section in the `pubspec.yaml` file.
|
||||||
class FlutterManifest {
|
class FlutterManifest {
|
||||||
FlutterManifest._();
|
FlutterManifest._();
|
||||||
@ -51,6 +53,36 @@ class FlutterManifest {
|
|||||||
|
|
||||||
String get appName => _descriptor['name'] ?? '';
|
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 {
|
bool get usesMaterialDesign {
|
||||||
return _flutterDescriptor['uses-material-design'] ?? false;
|
return _flutterDescriptor['uses-material-design'] ?? false;
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ Future<XcodeBuildResult> buildXcodeProject({
|
|||||||
final Directory appDirectory = fs.directory(app.appDirectory);
|
final Directory appDirectory = fs.directory(app.appDirectory);
|
||||||
await _addServicesToBundle(appDirectory);
|
await _addServicesToBundle(appDirectory);
|
||||||
|
|
||||||
updateGeneratedXcodeProperties(
|
await updateGeneratedXcodeProperties(
|
||||||
projectPath: fs.currentDirectory.path,
|
projectPath: fs.currentDirectory.path,
|
||||||
buildInfo: buildInfo,
|
buildInfo: buildInfo,
|
||||||
targetOverride: targetOverride,
|
targetOverride: targetOverride,
|
||||||
@ -272,53 +272,6 @@ Future<XcodeBuildResult> buildXcodeProject({
|
|||||||
await fingerprinter.writeFingerprint();
|
await fingerprinter.writeFingerprint();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If buildNumber is not specified, keep the project untouched.
|
|
||||||
if (buildInfo.buildNumber != null) {
|
|
||||||
final Status buildNumberStatus =
|
|
||||||
logger.startProgress('Setting CFBundleVersion...', expectSlowOperation: true);
|
|
||||||
try {
|
|
||||||
final RunResult buildNumberResult = await runAsync(
|
|
||||||
<String>[
|
|
||||||
'/usr/bin/env',
|
|
||||||
'xcrun',
|
|
||||||
'agvtool',
|
|
||||||
'new-version',
|
|
||||||
'-all',
|
|
||||||
buildInfo.buildNumber.toString(),
|
|
||||||
],
|
|
||||||
workingDirectory: app.appDirectory,
|
|
||||||
);
|
|
||||||
if (buildNumberResult.exitCode != 0) {
|
|
||||||
throwToolExit('Xcode failed to set new version\n${buildNumberResult.stderr}');
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
buildNumberStatus.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If buildName is not specified, keep the project untouched.
|
|
||||||
if (buildInfo.buildName != null) {
|
|
||||||
final Status buildNameStatus =
|
|
||||||
logger.startProgress('Setting CFBundleShortVersionString...', expectSlowOperation: true);
|
|
||||||
try {
|
|
||||||
final RunResult buildNameResult = await runAsync(
|
|
||||||
<String>[
|
|
||||||
'/usr/bin/env',
|
|
||||||
'xcrun',
|
|
||||||
'agvtool',
|
|
||||||
'new-marketing-version',
|
|
||||||
buildInfo.buildName,
|
|
||||||
],
|
|
||||||
workingDirectory: app.appDirectory,
|
|
||||||
);
|
|
||||||
if (buildNameResult.exitCode != 0) {
|
|
||||||
throwToolExit('Xcode failed to set new marketing version\n${buildNameResult.stderr}');
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
buildNameStatus.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<String> buildCommands = <String>[
|
final List<String> buildCommands = <String>[
|
||||||
'/usr/bin/env',
|
'/usr/bin/env',
|
||||||
'xcrun',
|
'xcrun',
|
||||||
|
@ -2,9 +2,12 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
import '../artifacts.dart';
|
import '../artifacts.dart';
|
||||||
|
import '../base/common.dart';
|
||||||
import '../base/context.dart';
|
import '../base/context.dart';
|
||||||
import '../base/file_system.dart';
|
import '../base/file_system.dart';
|
||||||
import '../base/io.dart';
|
import '../base/io.dart';
|
||||||
@ -15,6 +18,7 @@ import '../base/utils.dart';
|
|||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../bundle.dart' as bundle;
|
import '../bundle.dart' as bundle;
|
||||||
import '../cache.dart';
|
import '../cache.dart';
|
||||||
|
import '../flutter_manifest.dart';
|
||||||
import '../globals.dart';
|
import '../globals.dart';
|
||||||
|
|
||||||
final RegExp _settingExpr = new RegExp(r'(\w+)\s*=\s*(.*)$');
|
final RegExp _settingExpr = new RegExp(r'(\w+)\s*=\s*(.*)$');
|
||||||
@ -30,11 +34,11 @@ String _generatedXcodePropertiesPath(String projectPath) {
|
|||||||
|
|
||||||
/// Writes default Xcode properties files in the Flutter project at [projectPath],
|
/// Writes default Xcode properties files in the Flutter project at [projectPath],
|
||||||
/// if project is an iOS project and such files do not already exist.
|
/// if project is an iOS project and such files do not already exist.
|
||||||
void generateXcodeProperties(String projectPath) {
|
Future<void> generateXcodeProperties(String projectPath) async {
|
||||||
if (fs.isDirectorySync(fs.path.join(projectPath, 'ios'))) {
|
if (fs.isDirectorySync(fs.path.join(projectPath, 'ios'))) {
|
||||||
if (fs.file(_generatedXcodePropertiesPath(projectPath)).existsSync())
|
if (fs.file(_generatedXcodePropertiesPath(projectPath)).existsSync())
|
||||||
return;
|
return;
|
||||||
updateGeneratedXcodeProperties(
|
await updateGeneratedXcodeProperties(
|
||||||
projectPath: projectPath,
|
projectPath: projectPath,
|
||||||
buildInfo: BuildInfo.debug,
|
buildInfo: BuildInfo.debug,
|
||||||
targetOverride: bundle.defaultMainPath,
|
targetOverride: bundle.defaultMainPath,
|
||||||
@ -47,12 +51,12 @@ void generateXcodeProperties(String projectPath) {
|
|||||||
///
|
///
|
||||||
/// targetOverride: Optional parameter, if null or unspecified the default value
|
/// targetOverride: Optional parameter, if null or unspecified the default value
|
||||||
/// from xcode_backend.sh is used 'lib/main.dart'.
|
/// from xcode_backend.sh is used 'lib/main.dart'.
|
||||||
void updateGeneratedXcodeProperties({
|
Future<void> updateGeneratedXcodeProperties({
|
||||||
@required String projectPath,
|
@required String projectPath,
|
||||||
@required BuildInfo buildInfo,
|
@required BuildInfo buildInfo,
|
||||||
String targetOverride,
|
String targetOverride,
|
||||||
@required bool previewDart2,
|
@required bool previewDart2,
|
||||||
}) {
|
}) async {
|
||||||
final StringBuffer localsBuffer = new StringBuffer();
|
final StringBuffer localsBuffer = new StringBuffer();
|
||||||
|
|
||||||
localsBuffer.writeln('// This is a generated file; do not edit or check into version control.');
|
localsBuffer.writeln('// This is a generated file; do not edit or check into version control.');
|
||||||
@ -77,6 +81,24 @@ void updateGeneratedXcodeProperties({
|
|||||||
|
|
||||||
localsBuffer.writeln('FLUTTER_FRAMEWORK_DIR=${flutterFrameworkDir(buildInfo.mode)}');
|
localsBuffer.writeln('FLUTTER_FRAMEWORK_DIR=${flutterFrameworkDir(buildInfo.mode)}');
|
||||||
|
|
||||||
|
final String flutterManifest = fs.path.join(projectPath, bundle.defaultManifestPath);
|
||||||
|
FlutterManifest manifest;
|
||||||
|
try {
|
||||||
|
manifest = await FlutterManifest.createFromPath(flutterManifest);
|
||||||
|
} catch (error) {
|
||||||
|
throwToolExit('Failed to load pubspec.yaml: $error');
|
||||||
|
}
|
||||||
|
|
||||||
|
final String buildName = buildInfo?.buildName ?? manifest.buildName;
|
||||||
|
if (buildName != null) {
|
||||||
|
localsBuffer.writeln('FLUTTER_BUILD_NAME=$buildName');
|
||||||
|
}
|
||||||
|
|
||||||
|
final int buildNumber = buildInfo?.buildNumber ?? manifest.buildNumber;
|
||||||
|
if (buildNumber != null) {
|
||||||
|
localsBuffer.writeln('FLUTTER_BUILD_NUMBER=$buildNumber');
|
||||||
|
}
|
||||||
|
|
||||||
if (artifacts is LocalEngineArtifacts) {
|
if (artifacts is LocalEngineArtifacts) {
|
||||||
final LocalEngineArtifacts localEngineArtifacts = artifacts;
|
final LocalEngineArtifacts localEngineArtifacts = artifacts;
|
||||||
localsBuffer.writeln('LOCAL_ENGINE=${localEngineArtifacts.engineOutPath}');
|
localsBuffer.writeln('LOCAL_ENGINE=${localEngineArtifacts.engineOutPath}');
|
||||||
|
@ -55,12 +55,12 @@ class FlutterProject {
|
|||||||
|
|
||||||
/// Generates project files necessary to make Gradle builds work on Android
|
/// Generates project files necessary to make Gradle builds work on Android
|
||||||
/// and CocoaPods+Xcode work on iOS, for app projects only
|
/// and CocoaPods+Xcode work on iOS, for app projects only
|
||||||
void ensureReadyForPlatformSpecificTooling() {
|
Future<void> ensureReadyForPlatformSpecificTooling() async {
|
||||||
if (!directory.existsSync() || hasExampleApp) {
|
if (!directory.existsSync() || hasExampleApp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
injectPlugins(directory: directory.path);
|
injectPlugins(directory: directory.path);
|
||||||
generateXcodeProperties(directory.path);
|
await generateXcodeProperties(directory.path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,7 +329,7 @@ abstract class FlutterCommand extends Command<Null> {
|
|||||||
|
|
||||||
if (shouldRunPub) {
|
if (shouldRunPub) {
|
||||||
await pubGet(context: PubContext.getVerifyContext(name));
|
await pubGet(context: PubContext.getVerifyContext(name));
|
||||||
new FlutterProject(fs.currentDirectory).ensureReadyForPlatformSpecificTooling();
|
await new FlutterProject(fs.currentDirectory).ensureReadyForPlatformSpecificTooling();
|
||||||
}
|
}
|
||||||
|
|
||||||
setupApplicationPackages();
|
setupApplicationPackages();
|
||||||
|
@ -11,6 +11,16 @@ if (flutterRoot == null) {
|
|||||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
|
if (flutterVersionCode == null) {
|
||||||
|
throw new GradleException("versionCode not found. Define flutter.versionCode in the local.properties file.")
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
||||||
|
if (flutterVersionName == null) {
|
||||||
|
throw new GradleException("versionName not found. Define flutter.versionName in the local.properties file.")
|
||||||
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
@ -26,8 +36,8 @@ android {
|
|||||||
applicationId "{{androidIdentifier}}"
|
applicationId "{{androidIdentifier}}"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 27
|
targetSdkVersion 27
|
||||||
versionCode 1
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName "1.0"
|
versionName flutterVersionName
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,16 @@ if (flutterRoot == null) {
|
|||||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
|
if (flutterVersionCode == null) {
|
||||||
|
throw new GradleException("versionCode not found. Define flutter.versionCode in the local.properties file.")
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
||||||
|
if (flutterVersionName == null) {
|
||||||
|
throw new GradleException("versionName not found. Define flutter.versionName in the local.properties file.")
|
||||||
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
@ -31,8 +41,8 @@ android {
|
|||||||
applicationId "{{androidIdentifier}}"
|
applicationId "{{androidIdentifier}}"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 27
|
targetSdkVersion 27
|
||||||
versionCode 1
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName "1.0"
|
versionName flutterVersionName
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@
|
|||||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@ -393,7 +393,7 @@
|
|||||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
@ -368,7 +368,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@ -396,7 +396,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.0</string>
|
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
name: {{projectName}}
|
name: {{projectName}}
|
||||||
description: {{description}}
|
description: {{description}}
|
||||||
|
|
||||||
|
# The following defines the version and build number for your application.
|
||||||
|
# A version number is three numbers separated by dots, like 1.2.43
|
||||||
|
# followed by an optional build number separated by a +.
|
||||||
|
# Both the version and the builder number may be overridden in flutter
|
||||||
|
# build by specifying --build-name and --build-number, respectively.
|
||||||
|
# Read more about versioning at semver.org.
|
||||||
|
version: 1.0.0+1
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
@ -2,16 +2,20 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter_tools/src/android/gradle.dart';
|
import 'package:flutter_tools/src/android/gradle.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:flutter_tools/src/build_info.dart';
|
import 'package:flutter_tools/src/build_info.dart';
|
||||||
|
import 'package:flutter_tools/src/cache.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
import '../src/common.dart';
|
import '../src/common.dart';
|
||||||
|
import '../src/context.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('gradle build', () {
|
group('gradle build', () {
|
||||||
test('do not crash if there is no Android SDK', () {
|
test('do not crash if there is no Android SDK', () async {
|
||||||
Exception shouldBeToolExit;
|
Exception shouldBeToolExit;
|
||||||
try {
|
try {
|
||||||
// We'd like to always set androidSdk to null and test updateLocalProperties. But that's
|
// We'd like to always set androidSdk to null and test updateLocalProperties. But that's
|
||||||
@ -21,7 +25,7 @@ void main() {
|
|||||||
// This test is written to fail if our bots get Android SDKs in the future: shouldBeToolExit
|
// This test is written to fail if our bots get Android SDKs in the future: shouldBeToolExit
|
||||||
// will be null and our expectation would fail. That would remind us to make these tests
|
// will be null and our expectation would fail. That would remind us to make these tests
|
||||||
// hermetic before adding Android SDKs to the bots.
|
// hermetic before adding Android SDKs to the bots.
|
||||||
updateLocalProperties();
|
await updateLocalProperties();
|
||||||
} on Exception catch (e) {
|
} on Exception catch (e) {
|
||||||
shouldBeToolExit = e;
|
shouldBeToolExit = e;
|
||||||
}
|
}
|
||||||
@ -126,4 +130,181 @@ someOtherProperty: someOtherValue
|
|||||||
expect(project.assembleTaskFor(const BuildInfo(BuildMode.release, 'unknown')), isNull);
|
expect(project.assembleTaskFor(const BuildInfo(BuildMode.release, 'unknown')), isNull);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('Gradle local.properties', () {
|
||||||
|
Directory temp;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
Cache.disableLocking();
|
||||||
|
temp = fs.systemTempDirectory.createTempSync('flutter_tools');
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() {
|
||||||
|
temp.deleteSync(recursive: true);
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<String> createMinimalProject(String manifest) async {
|
||||||
|
final Directory directory = temp.childDirectory('android_project');
|
||||||
|
final File manifestFile = directory.childFile('pubspec.yaml');
|
||||||
|
manifestFile.createSync(recursive: true);
|
||||||
|
manifestFile.writeAsStringSync(manifest);
|
||||||
|
|
||||||
|
return directory.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
String propertyFor(String key, File file) {
|
||||||
|
return file
|
||||||
|
.readAsLinesSync()
|
||||||
|
.where((String line) => line.startsWith('$key='))
|
||||||
|
.map((String line) => line.split('=')[1])
|
||||||
|
.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> checkBuildVersion({
|
||||||
|
String manifest,
|
||||||
|
BuildInfo buildInfo,
|
||||||
|
String expectedBuildName,
|
||||||
|
String expectedBuildNumber,
|
||||||
|
}) async {
|
||||||
|
final String projectPath = await createMinimalProject(manifest);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await updateLocalProperties(projectPath: projectPath, buildInfo: buildInfo);
|
||||||
|
|
||||||
|
final String propertiesPath = fs.path.join(projectPath, 'android', 'local.properties');
|
||||||
|
final File localPropertiesFile = fs.file(propertiesPath);
|
||||||
|
|
||||||
|
expect(propertyFor('flutter.versionName', localPropertiesFile), expectedBuildName);
|
||||||
|
expect(propertyFor('flutter.versionCode', localPropertiesFile), expectedBuildNumber);
|
||||||
|
} on Exception {
|
||||||
|
// Android SDK not found, skip test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testUsingContext('extract build name and number from pubspec.yaml', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0+1
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null);
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.0',
|
||||||
|
expectedBuildNumber: '1',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('extract build name from pubspec.yaml', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null);
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.0',
|
||||||
|
expectedBuildNumber: null,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('allow build info to override build name', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0+1
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2');
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.2',
|
||||||
|
expectedBuildNumber: '1',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('allow build info to override build number', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0+1
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildNumber: 3);
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.0',
|
||||||
|
expectedBuildNumber: '3',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('allow build info to override build name and number', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0+1
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: 3);
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.2',
|
||||||
|
expectedBuildNumber: '3',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('allow build info to override build name and set number', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: 3);
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.2',
|
||||||
|
expectedBuildNumber: '3',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('allow build info to set build name and number', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: 3);
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.2',
|
||||||
|
expectedBuildNumber: '3',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:file/memory.dart';
|
import 'package:file/memory.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
@ -359,6 +361,118 @@ flutter:
|
|||||||
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
|
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
|
||||||
expect(flutterManifest.isEmpty, false);
|
expect(flutterManifest.isEmpty, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Future<void> checkManifestVersion({
|
||||||
|
String manifest,
|
||||||
|
String expectedAppVersion,
|
||||||
|
String expectedBuildName,
|
||||||
|
int expectedBuildNumber,
|
||||||
|
}) async {
|
||||||
|
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
|
||||||
|
expect(flutterManifest.appVersion, expectedAppVersion);
|
||||||
|
expect(flutterManifest.buildName, expectedBuildName);
|
||||||
|
expect(flutterManifest.buildNumber, expectedBuildNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
test('parses major.minor.patch+build version clause', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0+2
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
await checkManifestVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
expectedAppVersion: '1.0.0+2',
|
||||||
|
expectedBuildName: '1.0.0',
|
||||||
|
expectedBuildNumber: 2,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parses major.minor+build version clause', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0+2
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
await checkManifestVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
expectedAppVersion: '1.0+2',
|
||||||
|
expectedBuildName: '1.0',
|
||||||
|
expectedBuildNumber: 2,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parses major+build version clause', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1+2
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
await checkManifestVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
expectedAppVersion: '1+2',
|
||||||
|
expectedBuildName: '1',
|
||||||
|
expectedBuildNumber: 2,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parses major version clause', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
await checkManifestVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
expectedAppVersion: '1',
|
||||||
|
expectedBuildName: '1',
|
||||||
|
expectedBuildNumber: null,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parses empty version clause', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version:
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
await checkManifestVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
expectedAppVersion: null,
|
||||||
|
expectedBuildName: null,
|
||||||
|
expectedBuildNumber: null,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('parses no version clause', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
await checkManifestVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
expectedAppVersion: null,
|
||||||
|
expectedBuildName: null,
|
||||||
|
expectedBuildNumber: null,
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group('FlutterManifest with MemoryFileSystem', () {
|
group('FlutterManifest with MemoryFileSystem', () {
|
||||||
@ -371,8 +485,7 @@ dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
''';
|
''';
|
||||||
|
|
||||||
final FlutterManifest flutterManifest = await FlutterManifest
|
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
|
||||||
.createFromString(manifest);
|
|
||||||
expect(flutterManifest.isEmpty, false);
|
expect(flutterManifest.isEmpty, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,15 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:file/memory.dart';
|
import 'package:file/memory.dart';
|
||||||
import 'package:flutter_tools/src/artifacts.dart';
|
import 'package:flutter_tools/src/artifacts.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:flutter_tools/src/base/io.dart';
|
import 'package:flutter_tools/src/base/io.dart';
|
||||||
import 'package:flutter_tools/src/build_info.dart';
|
import 'package:flutter_tools/src/build_info.dart';
|
||||||
|
import 'package:flutter_tools/src/bundle.dart' as bundle;
|
||||||
|
import 'package:flutter_tools/src/cache.dart';
|
||||||
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mockito/mockito.dart';
|
||||||
import 'package:platform/platform.dart';
|
import 'package:platform/platform.dart';
|
||||||
@ -277,14 +281,14 @@ Information about project "Runner":
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () {
|
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () async {
|
||||||
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, any)).thenReturn('engine');
|
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, any)).thenReturn('engine');
|
||||||
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm'));
|
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm'));
|
||||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null,
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null,
|
||||||
previewDart2: true,
|
previewDart2: true,
|
||||||
targetPlatform: TargetPlatform.ios,
|
targetPlatform: TargetPlatform.ios,
|
||||||
);
|
);
|
||||||
updateGeneratedXcodeProperties(
|
await updateGeneratedXcodeProperties(
|
||||||
projectPath: 'path/to/project',
|
projectPath: 'path/to/project',
|
||||||
buildInfo: buildInfo,
|
buildInfo: buildInfo,
|
||||||
previewDart2: true,
|
previewDart2: true,
|
||||||
@ -297,14 +301,14 @@ Information about project "Runner":
|
|||||||
expect(contents.contains('ARCHS=armv7'), isTrue);
|
expect(contents.contains('ARCHS=armv7'), isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () {
|
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () async {
|
||||||
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, any)).thenReturn('engine');
|
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, any)).thenReturn('engine');
|
||||||
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile'));
|
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile'));
|
||||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null,
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null,
|
||||||
previewDart2: true,
|
previewDart2: true,
|
||||||
targetPlatform: TargetPlatform.ios,
|
targetPlatform: TargetPlatform.ios,
|
||||||
);
|
);
|
||||||
updateGeneratedXcodeProperties(
|
await updateGeneratedXcodeProperties(
|
||||||
projectPath: 'path/to/project',
|
projectPath: 'path/to/project',
|
||||||
buildInfo: buildInfo,
|
buildInfo: buildInfo,
|
||||||
previewDart2: true,
|
previewDart2: true,
|
||||||
@ -317,6 +321,185 @@ Information about project "Runner":
|
|||||||
expect(contents.contains('ARCHS=arm64'), isTrue);
|
expect(contents.contains('ARCHS=arm64'), isTrue);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('Xcode Generated.xcconfig', () {
|
||||||
|
Directory temp;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
Cache.disableLocking();
|
||||||
|
temp = fs.systemTempDirectory.createTempSync('flutter_tools');
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() {
|
||||||
|
temp.deleteSync(recursive: true);
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<String> createMinimalProject(String manifest) async {
|
||||||
|
final Directory directory = temp.childDirectory('ios_project');
|
||||||
|
final File manifestFile = directory.childFile('pubspec.yaml');
|
||||||
|
manifestFile.createSync(recursive: true);
|
||||||
|
manifestFile.writeAsStringSync(manifest);
|
||||||
|
|
||||||
|
return directory.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
String propertyFor(String key, File file) {
|
||||||
|
final List<String> properties = file
|
||||||
|
.readAsLinesSync()
|
||||||
|
.where((String line) => line.startsWith('$key='))
|
||||||
|
.map((String line) => line.split('=')[1])
|
||||||
|
.toList();
|
||||||
|
return properties.isEmpty ? null : properties.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> checkBuildVersion({
|
||||||
|
String manifest,
|
||||||
|
BuildInfo buildInfo,
|
||||||
|
String expectedBuildName,
|
||||||
|
String expectedBuildNumber,
|
||||||
|
}) async {
|
||||||
|
final String projectPath = await createMinimalProject(manifest);
|
||||||
|
|
||||||
|
await updateGeneratedXcodeProperties(
|
||||||
|
projectPath: projectPath,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
targetOverride: bundle.defaultMainPath,
|
||||||
|
previewDart2: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
final String propertiesPath = fs.path.join(projectPath, 'ios', 'Flutter', 'Generated.xcconfig');
|
||||||
|
final File localPropertiesFile = fs.file(propertiesPath);
|
||||||
|
|
||||||
|
expect(propertyFor('FLUTTER_BUILD_NAME', localPropertiesFile), expectedBuildName);
|
||||||
|
expect(propertyFor('FLUTTER_BUILD_NUMBER', localPropertiesFile), expectedBuildNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
testUsingContext('extract build name and number from pubspec.yaml', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0+1
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null);
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.0',
|
||||||
|
expectedBuildNumber: '1',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('extract build name from pubspec.yaml', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null);
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.0',
|
||||||
|
expectedBuildNumber: null,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('allow build info to override build name', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0+1
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2');
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.2',
|
||||||
|
expectedBuildNumber: '1',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('allow build info to override build number', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0+1
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildNumber: 3);
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.0',
|
||||||
|
expectedBuildNumber: '3',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('allow build info to override build name and number', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0+1
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: 3);
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.2',
|
||||||
|
expectedBuildNumber: '3',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('allow build info to override build name and set number', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
version: 1.0.0
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: 3);
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.2',
|
||||||
|
expectedBuildNumber: '3',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('allow build info to set build name and number', () async {
|
||||||
|
const String manifest = '''
|
||||||
|
name: test
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
''';
|
||||||
|
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: 3);
|
||||||
|
await checkBuildVersion(
|
||||||
|
manifest: manifest,
|
||||||
|
buildInfo: buildInfo,
|
||||||
|
expectedBuildName: '1.0.2',
|
||||||
|
expectedBuildNumber: '3',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Platform fakePlatform(String name) {
|
Platform fakePlatform(String name) {
|
||||||
|
@ -20,23 +20,23 @@ void main() {
|
|||||||
group('ensure ready for platform-specific tooling', () {
|
group('ensure ready for platform-specific tooling', () {
|
||||||
testInMemory('does nothing, if project is not created', () async {
|
testInMemory('does nothing, if project is not created', () async {
|
||||||
final FlutterProject project = someProject();
|
final FlutterProject project = someProject();
|
||||||
project.ensureReadyForPlatformSpecificTooling();
|
await project.ensureReadyForPlatformSpecificTooling();
|
||||||
expect(project.directory.existsSync(), isFalse);
|
expect(project.directory.existsSync(), isFalse);
|
||||||
});
|
});
|
||||||
testInMemory('does nothing in plugin or package root project', () async {
|
testInMemory('does nothing in plugin or package root project', () async {
|
||||||
final FlutterProject project = aPluginProject();
|
final FlutterProject project = aPluginProject();
|
||||||
project.ensureReadyForPlatformSpecificTooling();
|
await project.ensureReadyForPlatformSpecificTooling();
|
||||||
expect(project.ios.directory.childFile('Runner/GeneratedPluginRegistrant.h').existsSync(), isFalse);
|
expect(project.ios.directory.childFile('Runner/GeneratedPluginRegistrant.h').existsSync(), isFalse);
|
||||||
expect(project.ios.directory.childFile('Flutter/Generated.xcconfig').existsSync(), isFalse);
|
expect(project.ios.directory.childFile('Flutter/Generated.xcconfig').existsSync(), isFalse);
|
||||||
});
|
});
|
||||||
testInMemory('injects plugins', () async {
|
testInMemory('injects plugins', () async {
|
||||||
final FlutterProject project = aProjectWithIos();
|
final FlutterProject project = aProjectWithIos();
|
||||||
project.ensureReadyForPlatformSpecificTooling();
|
await project.ensureReadyForPlatformSpecificTooling();
|
||||||
expect(project.ios.directory.childFile('Runner/GeneratedPluginRegistrant.h').existsSync(), isTrue);
|
expect(project.ios.directory.childFile('Runner/GeneratedPluginRegistrant.h').existsSync(), isTrue);
|
||||||
});
|
});
|
||||||
testInMemory('generates Xcode configuration', () async {
|
testInMemory('generates Xcode configuration', () async {
|
||||||
final FlutterProject project = aProjectWithIos();
|
final FlutterProject project = aProjectWithIos();
|
||||||
project.ensureReadyForPlatformSpecificTooling();
|
await project.ensureReadyForPlatformSpecificTooling();
|
||||||
expect(project.ios.directory.childFile('Flutter/Generated.xcconfig').existsSync(), isTrue);
|
expect(project.ios.directory.childFile('Flutter/Generated.xcconfig').existsSync(), isTrue);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user