mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

When Swift Package Manager feature is enabled, create app and create plugin will have Swift Package Manager integration already added and will not need to undergo a migration. Fixes https://github.com/flutter/flutter/issues/146371. ``` flutter config --enable-swift-package-manager flutter create --ios-language swift --platforms ios,macos swift_app_name flutter create --ios-language objc --platforms ios objc_app_name flutter create --template=plugin --ios-language swift --platforms ios,macos swift_plugin_name flutter create --template=plugin --ios-language objc --platforms ios objc_plugin_name ```
380 lines
12 KiB
Dart
380 lines
12 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:convert';
|
|
|
|
import 'package:flutter_tools/src/base/file_system.dart';
|
|
import 'package:flutter_tools/src/base/io.dart';
|
|
|
|
import '../src/common.dart';
|
|
import 'test_utils.dart';
|
|
|
|
class SwiftPackageManagerUtils {
|
|
static Future<void> enableSwiftPackageManager(
|
|
String flutterBin,
|
|
String workingDirectory,
|
|
) async {
|
|
final ProcessResult result = await processManager.run(
|
|
<String>[
|
|
flutterBin,
|
|
...getLocalEngineArguments(),
|
|
'config',
|
|
'--enable-swift-package-manager',
|
|
'-v',
|
|
],
|
|
workingDirectory: workingDirectory,
|
|
);
|
|
expect(
|
|
result.exitCode,
|
|
0,
|
|
reason: 'Failed to enable Swift Package Manager: \n'
|
|
'stdout: \n${result.stdout}\n'
|
|
'stderr: \n${result.stderr}\n',
|
|
verbose: true,
|
|
);
|
|
}
|
|
|
|
static Future<void> disableSwiftPackageManager(
|
|
String flutterBin,
|
|
String workingDirectory,
|
|
) async {
|
|
final ProcessResult result = await processManager.run(
|
|
<String>[
|
|
flutterBin,
|
|
...getLocalEngineArguments(),
|
|
'config',
|
|
'--no-enable-swift-package-manager',
|
|
'-v',
|
|
],
|
|
workingDirectory: workingDirectory,
|
|
);
|
|
expect(
|
|
result.exitCode,
|
|
0,
|
|
reason: 'Failed to disable Swift Package Manager: \n'
|
|
'stdout: \n${result.stdout}\n'
|
|
'stderr: \n${result.stderr}\n',
|
|
verbose: true,
|
|
);
|
|
}
|
|
|
|
static Future<String> createApp(
|
|
String flutterBin,
|
|
String workingDirectory, {
|
|
required String platform,
|
|
required String iosLanguage,
|
|
required List<String> options,
|
|
bool usesSwiftPackageManager = false,
|
|
}) async {
|
|
final String appTemplateType = usesSwiftPackageManager ? 'spm' : 'default';
|
|
|
|
final String appName = '${platform}_${iosLanguage}_${appTemplateType}_app';
|
|
final ProcessResult result = await processManager.run(
|
|
<String>[
|
|
flutterBin,
|
|
...getLocalEngineArguments(),
|
|
'create',
|
|
'--org',
|
|
'io.flutter.devicelab',
|
|
'-i',
|
|
iosLanguage,
|
|
...options,
|
|
appName,
|
|
],
|
|
workingDirectory: workingDirectory,
|
|
);
|
|
|
|
expect(
|
|
result.exitCode,
|
|
0,
|
|
reason: 'Failed to create app: \n'
|
|
'stdout: \n${result.stdout}\n'
|
|
'stderr: \n${result.stderr}\n',
|
|
);
|
|
|
|
return fileSystem.path.join(
|
|
workingDirectory,
|
|
appName,
|
|
);
|
|
}
|
|
|
|
static Future<void> buildApp(
|
|
String flutterBin,
|
|
String workingDirectory, {
|
|
required List<String> options,
|
|
List<Pattern>? expectedLines,
|
|
List<String>? unexpectedLines,
|
|
}) async {
|
|
final List<Pattern> remainingExpectedLines = expectedLines ?? <Pattern>[];
|
|
final List<String> unexpectedLinesFound = <String>[];
|
|
final List<String> command = <String>[
|
|
flutterBin,
|
|
...getLocalEngineArguments(),
|
|
'build',
|
|
...options,
|
|
];
|
|
|
|
final ProcessResult result = await processManager.run(
|
|
command,
|
|
workingDirectory: workingDirectory,
|
|
);
|
|
|
|
final List<String> stdout = LineSplitter.split(result.stdout.toString()).toList();
|
|
final List<String> stderr = LineSplitter.split(result.stderr.toString()).toList();
|
|
final List<String> output = stdout + stderr;
|
|
for (final String line in output) {
|
|
// Remove "[ +3 ms] " prefix
|
|
String trimmedLine = line.trim();
|
|
if (trimmedLine.startsWith('[')) {
|
|
final int prefixEndIndex = trimmedLine.indexOf(']');
|
|
if (prefixEndIndex > 0) {
|
|
trimmedLine = trimmedLine
|
|
.substring(prefixEndIndex + 1, trimmedLine.length)
|
|
.trim();
|
|
}
|
|
}
|
|
remainingExpectedLines.remove(trimmedLine);
|
|
remainingExpectedLines.removeWhere((Pattern expectedLine) => trimmedLine.contains(expectedLine));
|
|
if (unexpectedLines != null && unexpectedLines.contains(trimmedLine)) {
|
|
unexpectedLinesFound.add(trimmedLine);
|
|
}
|
|
}
|
|
expect(
|
|
result.exitCode,
|
|
0,
|
|
reason: 'Failed to build app for "${command.join(' ')}":\n'
|
|
'stdout: \n${result.stdout}\n'
|
|
'stderr: \n${result.stderr}\n',
|
|
);
|
|
expect(
|
|
remainingExpectedLines,
|
|
isEmpty,
|
|
reason: 'Did not find expected lines for "${command.join(' ')}":\n'
|
|
'stdout: \n${result.stdout}\n'
|
|
'stderr: \n${result.stderr}\n',
|
|
);
|
|
expect(
|
|
unexpectedLinesFound,
|
|
isEmpty,
|
|
reason: 'Found unexpected lines for "${command.join(' ')}":\n'
|
|
'stdout: \n${result.stdout}\n'
|
|
'stderr: \n${result.stderr}\n',
|
|
);
|
|
}
|
|
|
|
static Future<void> cleanApp(String flutterBin, String workingDirectory) async {
|
|
final ProcessResult result = await processManager.run(
|
|
<String>[
|
|
flutterBin,
|
|
...getLocalEngineArguments(),
|
|
'clean',
|
|
],
|
|
workingDirectory: workingDirectory,
|
|
);
|
|
expect(
|
|
result.exitCode,
|
|
0,
|
|
reason: 'Failed to clean app: \n'
|
|
'stdout: \n${result.stdout}\n'
|
|
'stderr: \n${result.stderr}\n',
|
|
);
|
|
}
|
|
|
|
static Future<SwiftPackageManagerPlugin> createPlugin(
|
|
String flutterBin,
|
|
String workingDirectory, {
|
|
required String platform,
|
|
required String iosLanguage,
|
|
bool usesSwiftPackageManager = false,
|
|
}) async {
|
|
final String dependencyManager = usesSwiftPackageManager ? 'spm' : 'cocoapods';
|
|
|
|
// Create plugin
|
|
final String pluginName = '${platform}_${iosLanguage}_${dependencyManager}_plugin';
|
|
final ProcessResult result = await processManager.run(
|
|
<String>[
|
|
flutterBin,
|
|
...getLocalEngineArguments(),
|
|
'create',
|
|
'--org',
|
|
'io.flutter.devicelab',
|
|
'--template=plugin',
|
|
'--platforms=$platform',
|
|
'-i',
|
|
iosLanguage,
|
|
pluginName,
|
|
],
|
|
workingDirectory: workingDirectory,
|
|
);
|
|
|
|
expect(
|
|
result.exitCode,
|
|
0,
|
|
reason: 'Failed to create plugin: \n'
|
|
'stdout: \n${result.stdout}\n'
|
|
'stderr: \n${result.stderr}\n',
|
|
);
|
|
|
|
final Directory pluginDirectory = fileSystem.directory(
|
|
fileSystem.path.join(workingDirectory, pluginName),
|
|
);
|
|
|
|
return SwiftPackageManagerPlugin(
|
|
pluginName: pluginName,
|
|
pluginPath: pluginDirectory.path,
|
|
platform: platform,
|
|
);
|
|
}
|
|
|
|
static void addDependency({
|
|
required SwiftPackageManagerPlugin plugin,
|
|
required String appDirectoryPath,
|
|
}) {
|
|
final File pubspec = fileSystem.file(
|
|
fileSystem.path.join(appDirectoryPath, 'pubspec.yaml'),
|
|
);
|
|
final String pubspecContent = pubspec.readAsStringSync();
|
|
pubspec.writeAsStringSync(
|
|
pubspecContent.replaceFirst(
|
|
'\ndependencies:\n',
|
|
'\ndependencies:\n ${plugin.pluginName}:\n path: ${plugin.pluginPath}\n',
|
|
),
|
|
);
|
|
}
|
|
|
|
static void disableSwiftPackageManagerByPubspec({
|
|
required String appDirectoryPath,
|
|
}) {
|
|
final File pubspec = fileSystem.file(
|
|
fileSystem.path.join(appDirectoryPath, 'pubspec.yaml'),
|
|
);
|
|
final String pubspecContent = pubspec.readAsStringSync();
|
|
pubspec.writeAsStringSync(
|
|
pubspecContent.replaceFirst(
|
|
'\n# The following section is specific to Flutter packages.\nflutter:\n',
|
|
'\n# The following section is specific to Flutter packages.\nflutter:\n disable-swift-package-manager: true',
|
|
),
|
|
);
|
|
}
|
|
|
|
static SwiftPackageManagerPlugin integrationTestPlugin(String platform) {
|
|
final String flutterRoot = getFlutterRoot();
|
|
return SwiftPackageManagerPlugin(
|
|
platform: platform,
|
|
pluginName:
|
|
(platform == 'ios') ? 'integration_test' : 'integration_test_macos',
|
|
pluginPath: (platform == 'ios')
|
|
? fileSystem.path.join(flutterRoot, 'packages', 'integration_test')
|
|
: fileSystem.path.join(flutterRoot, 'packages', 'integration_test', 'integration_test_macos'),
|
|
);
|
|
}
|
|
|
|
static List<Pattern> expectedLines({
|
|
required String platform,
|
|
required String appDirectoryPath,
|
|
SwiftPackageManagerPlugin? cocoaPodsPlugin,
|
|
SwiftPackageManagerPlugin? swiftPackagePlugin,
|
|
bool swiftPackageMangerEnabled = false,
|
|
bool migrated = false,
|
|
}) {
|
|
final String frameworkName = platform == 'ios' ? 'Flutter' : 'FlutterMacOS';
|
|
final String appPlatformDirectoryPath = fileSystem.path.join(
|
|
appDirectoryPath,
|
|
platform,
|
|
);
|
|
|
|
final List<Pattern> expectedLines = <Pattern>[];
|
|
if (swiftPackageMangerEnabled) {
|
|
expectedLines.addAll(<String>[
|
|
'FlutterGeneratedPluginSwiftPackage: $appPlatformDirectoryPath/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage',
|
|
"➜ Explicit dependency on target 'FlutterGeneratedPluginSwiftPackage' in project 'FlutterGeneratedPluginSwiftPackage'",
|
|
]);
|
|
}
|
|
if (swiftPackagePlugin != null) {
|
|
// If using a Swift Package plugin, but Swift Package Manager is not enabled, it falls back to being used as a CocoaPods plugin.
|
|
if (swiftPackageMangerEnabled) {
|
|
expectedLines.addAll(<Pattern>[
|
|
RegExp('${swiftPackagePlugin.pluginName}: [/private]*${swiftPackagePlugin.pluginPath}/$platform/${swiftPackagePlugin.pluginName} @ local'),
|
|
"➜ Explicit dependency on target '${swiftPackagePlugin.pluginName}' in project '${swiftPackagePlugin.pluginName}'",
|
|
]);
|
|
} else {
|
|
expectedLines.addAll(<String>[
|
|
'-> Installing ${swiftPackagePlugin.pluginName} (0.0.1)',
|
|
"➜ Explicit dependency on target '${swiftPackagePlugin.pluginName}' in project 'Pods'",
|
|
]);
|
|
}
|
|
}
|
|
if (cocoaPodsPlugin != null) {
|
|
expectedLines.addAll(<String>[
|
|
'Running pod install...',
|
|
'-> Installing $frameworkName (1.0.0)',
|
|
'-> Installing ${cocoaPodsPlugin.pluginName} (0.0.1)',
|
|
"Target 'Pods-Runner' in project 'Pods'",
|
|
"➜ Explicit dependency on target '$frameworkName' in project 'Pods'",
|
|
"➜ Explicit dependency on target '${cocoaPodsPlugin.pluginName}' in project 'Pods'",
|
|
]);
|
|
}
|
|
if (migrated) {
|
|
expectedLines.addAll(<String>[
|
|
'Adding Swift Package Manager integration...',
|
|
'Running pod install...',
|
|
"Target 'Pods-Runner' in project 'Pods'",
|
|
]);
|
|
}
|
|
return expectedLines;
|
|
}
|
|
|
|
static List<String> unexpectedLines({
|
|
required String platform,
|
|
required String appDirectoryPath,
|
|
SwiftPackageManagerPlugin? cocoaPodsPlugin,
|
|
SwiftPackageManagerPlugin? swiftPackagePlugin,
|
|
bool swiftPackageMangerEnabled = false,
|
|
bool migrated = false,
|
|
}) {
|
|
final String frameworkName = platform == 'ios' ? 'Flutter' : 'FlutterMacOS';
|
|
final List<String> unexpectedLines = <String>[];
|
|
if (cocoaPodsPlugin == null && !migrated) {
|
|
unexpectedLines.addAll(<String>[
|
|
'Running pod install...',
|
|
'-> Installing $frameworkName (1.0.0)',
|
|
"Target 'Pods-Runner' in project 'Pods'",
|
|
]);
|
|
}
|
|
if (swiftPackagePlugin != null) {
|
|
if (swiftPackageMangerEnabled) {
|
|
unexpectedLines.addAll(<String>[
|
|
'-> Installing ${swiftPackagePlugin.pluginName} (0.0.1)',
|
|
"➜ Explicit dependency on target '${swiftPackagePlugin.pluginName}' in project 'Pods'",
|
|
]);
|
|
} else {
|
|
unexpectedLines.addAll(<String>[
|
|
'${swiftPackagePlugin.pluginName}: ${swiftPackagePlugin.pluginPath}/$platform/${swiftPackagePlugin.pluginName} @ local',
|
|
"➜ Explicit dependency on target '${swiftPackagePlugin.pluginName}' in project '${swiftPackagePlugin.pluginName}'",
|
|
]);
|
|
}
|
|
}
|
|
if (!migrated) {
|
|
unexpectedLines.addAll(<String>[
|
|
'Adding Swift Package Manager integration...',
|
|
]);
|
|
}
|
|
return unexpectedLines;
|
|
}
|
|
}
|
|
|
|
class SwiftPackageManagerPlugin {
|
|
SwiftPackageManagerPlugin({
|
|
required this.pluginName,
|
|
required this.pluginPath,
|
|
required this.platform,
|
|
});
|
|
|
|
final String pluginName;
|
|
final String pluginPath;
|
|
final String platform;
|
|
String get exampleAppPath => fileSystem.path.join(pluginPath, 'example');
|
|
String get exampleAppPlatformPath => fileSystem.path.join(exampleAppPath, platform);
|
|
}
|