mirror of
https://github.com/flutter/packages.git
synced 2025-06-19 05:30:13 +08:00
[tool/ci] Add iOS/macOS and Dart support to fetch-deps
(#4562)
Adds `fetch-deps` support for: - iOS/macOS dependencies, using `pod install` - Dart package dependencies, using `pub get` To make avoid doing extra work in the Dart dependencies step when using this with `*_platform_tests` CI, also adds flags for all of the other platforms, and adds a flag that allows skipping Dart dependencies for any package that doesn't have an example supporting any requested platform. This means that we can pass, e.g., `--windows --supporting-target-platforms-only` to only fetch Dart packages for packages with examples that will be build during the build-and-drive Windows tests. Adds this as a new step in every platform tests CI task, and in the standard analyze step, so that we will pre-fetch Dart packages (and for iOS/macOS, pods). This won't yet fully eliminate later network access (see https://github.com/flutter/flutter/issues/131204), but will give us early warning on any major failures, such as pub being entirely unreachable from the bots. - These are marked as an infrastructure step; we'll have to see if this ends up being confusing in practice. If `pub` resolution fails for legitimate reasons, such as a PR that tries to require a version of a package that doesn't exist or that has conflicts, this will cause a failure that is marked as infra. My assumption is that the much more common case is going to be that it is actually an infra failure. Fixes https://github.com/flutter/flutter/issues/130280
This commit is contained in:
@ -4,6 +4,10 @@ tasks:
|
||||
infra_step: true # Note infra steps failing prevents "always" from running.
|
||||
- name: analyze repo tools
|
||||
script: .ci/scripts/analyze_repo_tools.sh
|
||||
- name: download Dart deps
|
||||
script: script/tool_runner.sh
|
||||
args: ["fetch-deps"]
|
||||
infra_step: true
|
||||
- name: analyze
|
||||
script: script/tool_runner.sh
|
||||
# DO NOT change the custom-analysis argument here without changing the Dart repo.
|
||||
|
@ -2,10 +2,10 @@ tasks:
|
||||
- name: prepare tool
|
||||
script: .ci/scripts/prepare_tool.sh
|
||||
infra_step: true # Note infra steps failing prevents "always" from running.
|
||||
- name: download android deps
|
||||
- name: download Dart and Android deps
|
||||
script: script/tool_runner.sh
|
||||
infra_step: true
|
||||
args: ["fetch-deps"]
|
||||
args: ["fetch-deps", "--android", "--supporting-target-platforms-only"]
|
||||
- name: build examples
|
||||
script: script/tool_runner.sh
|
||||
args: ["build-examples", "--apk"]
|
||||
|
@ -5,6 +5,10 @@ tasks:
|
||||
- name: create simulator
|
||||
script: .ci/scripts/create_simulator.sh
|
||||
infra_step: true # Note infra steps failing prevents "always" from running.
|
||||
- name: download Dart and iOS deps
|
||||
script: script/tool_runner.sh
|
||||
args: ["fetch-deps", "--ios", "--supporting-target-platforms-only"]
|
||||
infra_step: true
|
||||
- name: build examples
|
||||
script: script/tool_runner.sh
|
||||
args: ["build-examples", "--ios"]
|
||||
|
@ -3,6 +3,11 @@ tasks:
|
||||
script: .ci/scripts/prepare_tool.sh
|
||||
- name: set default apps
|
||||
script: .ci/scripts/set_default_linux_apps.sh
|
||||
infra_step: true
|
||||
- name: download Dart deps
|
||||
script: script/tool_runner.sh
|
||||
args: ["fetch-deps", "--linux", "--supporting-target-platforms-only"]
|
||||
infra_step: true
|
||||
- name: build examples
|
||||
script: script/tool_runner.sh
|
||||
args: ["build-examples", "--linux"]
|
||||
|
@ -2,6 +2,10 @@ tasks:
|
||||
- name: prepare tool
|
||||
script: .ci/scripts/prepare_tool.sh
|
||||
infra_step: true # Note infra steps failing prevents "always" from running.
|
||||
- name: download Dart and macOS deps
|
||||
script: script/tool_runner.sh
|
||||
args: ["fetch-deps", "--macos", "--supporting-target-platforms-only"]
|
||||
infra_step: true
|
||||
- name: build examples
|
||||
script: script/tool_runner.sh
|
||||
args: ["build-examples", "--macos"]
|
||||
|
@ -2,6 +2,10 @@ tasks:
|
||||
- name: prepare tool
|
||||
script: .ci/scripts/prepare_tool.sh
|
||||
infra_step: true # Note infra steps failing prevents "always" from running.
|
||||
- name: download Dart deps
|
||||
script: script/tool_runner.sh
|
||||
args: ["fetch-deps", "--web", "--supporting-target-platforms-only"]
|
||||
infra_step: true
|
||||
- name: build examples
|
||||
script: script/tool_runner.sh
|
||||
args: ["build-examples", "--web"]
|
||||
|
@ -2,6 +2,10 @@ tasks:
|
||||
- name: prepare tool
|
||||
script: .ci/scripts/prepare_tool.sh
|
||||
infra_step: true # Note infra steps failing prevents "always" from running.
|
||||
- name: download Dart deps
|
||||
script: script/tool_runner.sh
|
||||
args: ["fetch-deps", "--windows", "--supporting-target-platforms-only"]
|
||||
infra_step: true
|
||||
- name: build examples (Win32)
|
||||
script: .ci/scripts/build_examples_win32.sh
|
||||
- name: native unit tests (Win32)
|
||||
|
@ -176,9 +176,8 @@ class BuildExamplesCommand extends PackageLoopingCommand {
|
||||
// supported platforms. For packages, just log and skip any requested
|
||||
// platform that a package doesn't have set up.
|
||||
if (!isPlugin &&
|
||||
!example.directory
|
||||
.childDirectory(platform.flutterPlatformDirectory)
|
||||
.existsSync()) {
|
||||
!example.appSupportsPlatform(
|
||||
getPlatformByName(platform.pluginPlatform))) {
|
||||
print('Skipping ${platform.label} for $packageName; not supported.');
|
||||
continue;
|
||||
}
|
||||
@ -304,11 +303,6 @@ class _PlatformDetails {
|
||||
/// The `flutter build` build type.
|
||||
final String flutterBuildType;
|
||||
|
||||
/// The Flutter platform directory name.
|
||||
// In practice, this is the same as the plugin platform key for all platforms.
|
||||
// If that changes, this can be adjusted.
|
||||
String get flutterPlatformDirectory => pluginPlatform;
|
||||
|
||||
/// Any extra flags to pass to `flutter build`.
|
||||
final List<String> extraBuildFlags;
|
||||
}
|
||||
|
@ -37,6 +37,25 @@ const String kEnableExperiment = 'enable-experiment';
|
||||
// ignore: public_member_api_docs
|
||||
enum FlutterPlatform { android, ios, linux, macos, web, windows }
|
||||
|
||||
const Map<String, FlutterPlatform> _platformByName = <String, FlutterPlatform>{
|
||||
platformAndroid: FlutterPlatform.android,
|
||||
platformIOS: FlutterPlatform.ios,
|
||||
platformLinux: FlutterPlatform.linux,
|
||||
platformMacOS: FlutterPlatform.macos,
|
||||
platformWeb: FlutterPlatform.web,
|
||||
platformWindows: FlutterPlatform.windows,
|
||||
};
|
||||
|
||||
/// Maps from a platform name (e.g., flag or platform directory) to the
|
||||
/// corresponding platform enum.
|
||||
FlutterPlatform getPlatformByName(String name) {
|
||||
final FlutterPlatform? platform = _platformByName[name];
|
||||
if (platform == null) {
|
||||
throw ArgumentError('Invalid platform: $name');
|
||||
}
|
||||
return platform;
|
||||
}
|
||||
|
||||
// Flutter->Dart SDK version mapping. Any time a command fails to look up a
|
||||
// corresponding version, this map should be updated.
|
||||
final Map<Version, Version> _dartSdkForFlutterSdk = <Version, Version>{
|
||||
|
@ -30,12 +30,13 @@ class ProcessRunner {
|
||||
String executable,
|
||||
List<String> args, {
|
||||
Directory? workingDir,
|
||||
Map<String, String>? environment,
|
||||
bool exitOnError = false,
|
||||
}) async {
|
||||
print(
|
||||
'Running command: "$executable ${args.join(' ')}" in ${workingDir?.path ?? io.Directory.current.path}');
|
||||
final io.Process process = await io.Process.start(executable, args,
|
||||
workingDirectory: workingDir?.path);
|
||||
workingDirectory: workingDir?.path, environment: environment);
|
||||
await Future.wait(<Future<dynamic>>[
|
||||
io.stdout.addStream(process.stdout),
|
||||
io.stderr.addStream(process.stderr),
|
||||
@ -62,14 +63,19 @@ class ProcessRunner {
|
||||
/// Defaults to `false`
|
||||
///
|
||||
/// Returns the [io.ProcessResult] of the [executable].
|
||||
Future<io.ProcessResult> run(String executable, List<String> args,
|
||||
{Directory? workingDir,
|
||||
bool exitOnError = false,
|
||||
bool logOnError = false,
|
||||
Encoding stdoutEncoding = io.systemEncoding,
|
||||
Encoding stderrEncoding = io.systemEncoding}) async {
|
||||
Future<io.ProcessResult> run(
|
||||
String executable,
|
||||
List<String> args, {
|
||||
Directory? workingDir,
|
||||
Map<String, String>? environment,
|
||||
bool exitOnError = false,
|
||||
bool logOnError = false,
|
||||
Encoding stdoutEncoding = io.systemEncoding,
|
||||
Encoding stderrEncoding = io.systemEncoding,
|
||||
}) async {
|
||||
final io.ProcessResult result = await io.Process.run(executable, args,
|
||||
workingDirectory: workingDir?.path,
|
||||
environment: environment,
|
||||
stdoutEncoding: stdoutEncoding,
|
||||
stderrEncoding: stderrEncoding);
|
||||
if (result.exitCode != 0) {
|
||||
|
@ -92,6 +92,16 @@ class RepositoryPackage {
|
||||
return directory.childDirectory(directoryName);
|
||||
}
|
||||
|
||||
/// Returns true if the package is an app that supports [platform].
|
||||
///
|
||||
/// The "app" prefix on this method is because this currently only works
|
||||
/// for app packages (e.g., examples).
|
||||
// TODO(stuartmorgan): Add support for non-app packages, by parsing the
|
||||
// pubspec for `flutter:platform:` or `platform:` sections.
|
||||
bool appSupportsPlatform(FlutterPlatform platform) {
|
||||
return platformDirectory(platform).existsSync();
|
||||
}
|
||||
|
||||
late final Pubspec _parsedPubspec =
|
||||
Pubspec.parse(pubspecFile.readAsStringSync());
|
||||
|
||||
|
@ -254,7 +254,7 @@ class DriveExamplesCommand extends PackageLoopingCommand {
|
||||
for (final MapEntry<String, List<String>> entry
|
||||
in _targetDeviceFlags.entries) {
|
||||
final String platform = entry.key;
|
||||
if (example.directory.childDirectory(platform).existsSync()) {
|
||||
if (example.appSupportsPlatform(getPlatformByName(platform))) {
|
||||
deviceFlags.addAll(entry.value);
|
||||
} else {
|
||||
final String exampleName =
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:file/file.dart';
|
||||
|
||||
import 'common/core.dart';
|
||||
import 'common/gradle.dart';
|
||||
@ -10,12 +11,15 @@ import 'common/package_looping_command.dart';
|
||||
import 'common/plugin_utils.dart';
|
||||
import 'common/repository_package.dart';
|
||||
|
||||
/// Download dependencies for the following platforms {android}.
|
||||
const int _exitPrecacheFailed = 3;
|
||||
const int _exitNothingRequested = 4;
|
||||
|
||||
/// Download dependencies, both Dart and native.
|
||||
///
|
||||
/// Specficially each platform runs:
|
||||
/// Android: 'gradlew dependencies'.
|
||||
/// Dart: TBD (flutter/flutter/issues/130279)
|
||||
/// iOS: TBD (flutter/flutter/issues/130280)
|
||||
/// Dart: 'flutter pub get'.
|
||||
/// iOS/macOS: 'pod install'.
|
||||
///
|
||||
/// See https://docs.gradle.org/6.4/userguide/core_dependency_management.html#sec:dependency-mgmt-in-gradle.
|
||||
class FetchDepsCommand extends PackageLoopingCommand {
|
||||
@ -24,25 +28,153 @@ class FetchDepsCommand extends PackageLoopingCommand {
|
||||
super.packagesDir, {
|
||||
super.processRunner,
|
||||
super.platform,
|
||||
});
|
||||
}) {
|
||||
argParser.addFlag(_dartFlag, defaultsTo: true, help: 'Run "pub get"');
|
||||
argParser.addFlag(_supportingTargetPlatformsOnlyFlag,
|
||||
help: 'Restricts "pub get" runs to packages that have at least one '
|
||||
'example supporting at least one of the platform flags passed.\n'
|
||||
'If no platform flags are passed, this will exclude all packages.');
|
||||
argParser.addFlag(platformAndroid,
|
||||
help: 'Run "gradlew dependencies" for Android plugins.\n'
|
||||
'Include packages with Android examples when used with '
|
||||
'--$_supportingTargetPlatformsOnlyFlag');
|
||||
argParser.addFlag(platformIOS,
|
||||
help: 'Run "pod install" for iOS plugins.\n'
|
||||
'Include packages with iOS examples when used with '
|
||||
'--$_supportingTargetPlatformsOnlyFlag');
|
||||
argParser.addFlag(platformLinux,
|
||||
help: 'Include packages with Linux examples when used with '
|
||||
'--$_supportingTargetPlatformsOnlyFlag');
|
||||
argParser.addFlag(platformMacOS,
|
||||
help: 'Run "pod install" for macOS plugins.\n'
|
||||
'Include packages with macOS examples when used with '
|
||||
'--$_supportingTargetPlatformsOnlyFlag');
|
||||
argParser.addFlag(platformWeb,
|
||||
help: 'Include packages with Web examples when used with '
|
||||
'--$_supportingTargetPlatformsOnlyFlag');
|
||||
argParser.addFlag(platformWindows,
|
||||
help: 'Include packages with Windows examples when used with '
|
||||
'--$_supportingTargetPlatformsOnlyFlag');
|
||||
}
|
||||
|
||||
static const String _dartFlag = 'dart';
|
||||
static const String _supportingTargetPlatformsOnlyFlag =
|
||||
'supporting-target-platforms-only';
|
||||
|
||||
static const Iterable<String> _platforms = <String>[
|
||||
platformAndroid,
|
||||
platformIOS,
|
||||
platformLinux,
|
||||
platformMacOS,
|
||||
platformWeb,
|
||||
platformWindows,
|
||||
];
|
||||
|
||||
@override
|
||||
final String name = 'fetch-deps';
|
||||
|
||||
@override
|
||||
final String description = 'Fetches dependencies for plugins.\n'
|
||||
'Runs "gradlew dependencies" on Android plugins.\n'
|
||||
'Dart see flutter/flutter/issues/130279\n'
|
||||
'iOS plugins see flutter/flutter/issues/130280\n'
|
||||
'\n'
|
||||
'Requires the examples to have been built at least once before running.';
|
||||
final String description = 'Fetches dependencies for packages';
|
||||
|
||||
@override
|
||||
Future<void> initializeRun() async {
|
||||
// `pod install` requires having the platform artifacts precached. See
|
||||
// https://github.com/flutter/flutter/blob/fb7a763c640d247d090cbb373e4b3a0459ac171b/packages/flutter_tools/bin/podhelper.rb#L47
|
||||
// https://github.com/flutter/flutter/blob/fb7a763c640d247d090cbb373e4b3a0459ac171b/packages/flutter_tools/bin/podhelper.rb#L130
|
||||
if (getBoolArg(platformIOS)) {
|
||||
final int exitCode = await processRunner.runAndStream(
|
||||
flutterCommand,
|
||||
<String>['precache', '--ios'],
|
||||
);
|
||||
if (exitCode != 0) {
|
||||
throw ToolExit(_exitPrecacheFailed);
|
||||
}
|
||||
}
|
||||
if (getBoolArg(platformMacOS)) {
|
||||
final int exitCode = await processRunner.runAndStream(
|
||||
flutterCommand,
|
||||
<String>['precache', '--macos'],
|
||||
);
|
||||
if (exitCode != 0) {
|
||||
throw ToolExit(_exitPrecacheFailed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PackageResult> runForPackage(RepositoryPackage package) async {
|
||||
bool fetchedDeps = false;
|
||||
final List<String> skips = <String>[];
|
||||
if (getBoolArg(_dartFlag)) {
|
||||
final bool filterPlatforms =
|
||||
getBoolArg(_supportingTargetPlatformsOnlyFlag);
|
||||
if (!filterPlatforms || _hasExampleSupportingRequestedPlatform(package)) {
|
||||
fetchedDeps = true;
|
||||
if (!await _fetchDartPackages(package)) {
|
||||
// If Dart-level depenendencies fail, fail immediately since the
|
||||
// native dependencies won't be useful.
|
||||
return PackageResult.fail(<String>['Failed to "pub get".']);
|
||||
}
|
||||
} else {
|
||||
skips.add('Skipping Dart dependencies; no examples support requested '
|
||||
'platforms.');
|
||||
}
|
||||
}
|
||||
|
||||
final List<String> errors = <String>[];
|
||||
for (final FlutterPlatform platform in _targetPlatforms) {
|
||||
final PackageResult result;
|
||||
switch (platform) {
|
||||
case FlutterPlatform.android:
|
||||
result = await _fetchAndroidDeps(package);
|
||||
break;
|
||||
case FlutterPlatform.ios:
|
||||
result = await _fetchDarwinDeps(package, platformIOS);
|
||||
break;
|
||||
case FlutterPlatform.macos:
|
||||
result = await _fetchDarwinDeps(package, platformMacOS);
|
||||
break;
|
||||
case FlutterPlatform.linux:
|
||||
case FlutterPlatform.web:
|
||||
case FlutterPlatform.windows:
|
||||
// No native dependency handling yet.
|
||||
result = PackageResult.skip('Nothing to do for $platform.');
|
||||
break;
|
||||
}
|
||||
switch (result.state) {
|
||||
case RunState.succeeded:
|
||||
fetchedDeps = true;
|
||||
break;
|
||||
case RunState.skipped:
|
||||
skips.add(result.details.first);
|
||||
break;
|
||||
case RunState.failed:
|
||||
errors.addAll(result.details);
|
||||
break;
|
||||
case RunState.excluded:
|
||||
throw StateError('Unreachable');
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.isNotEmpty) {
|
||||
return PackageResult.fail(errors);
|
||||
}
|
||||
if (fetchedDeps) {
|
||||
return PackageResult.success();
|
||||
}
|
||||
if (skips.isNotEmpty) {
|
||||
return PackageResult.skip(<String>['', ...skips].join('\n- '));
|
||||
}
|
||||
|
||||
printError('At least one type of dependency must be requested');
|
||||
throw ToolExit(_exitNothingRequested);
|
||||
}
|
||||
|
||||
Future<PackageResult> _fetchAndroidDeps(RepositoryPackage package) async {
|
||||
if (!pluginSupportsPlatform(platformAndroid, package,
|
||||
requiredMode: PlatformSupport.inline)) {
|
||||
return PackageResult.skip(
|
||||
'Plugin does not have an Android implementation.');
|
||||
'Package does not have native Android dependencies.');
|
||||
}
|
||||
|
||||
for (final RepositoryPackage example in package.getExamples()) {
|
||||
@ -63,7 +195,8 @@ class FetchDepsCommand extends PackageLoopingCommand {
|
||||
|
||||
final String packageName = package.directory.basename;
|
||||
|
||||
final int exitCode = await gradleProject.runCommand('$packageName:dependencies');
|
||||
final int exitCode =
|
||||
await gradleProject.runCommand('$packageName:dependencies');
|
||||
if (exitCode != 0) {
|
||||
return PackageResult.fail();
|
||||
}
|
||||
@ -71,4 +204,78 @@ class FetchDepsCommand extends PackageLoopingCommand {
|
||||
|
||||
return PackageResult.success();
|
||||
}
|
||||
|
||||
Future<PackageResult> _fetchDarwinDeps(
|
||||
RepositoryPackage package, final String platform) async {
|
||||
if (!pluginSupportsPlatform(platform, package,
|
||||
requiredMode: PlatformSupport.inline)) {
|
||||
// Convert from the flag (lower case ios/macos) to the actual name.
|
||||
final String displayPlatform = platform.replaceFirst('os', 'OS');
|
||||
return PackageResult.skip(
|
||||
'Package does not have native $displayPlatform dependencies.');
|
||||
}
|
||||
|
||||
for (final RepositoryPackage example in package.getExamples()) {
|
||||
final Directory platformDir =
|
||||
example.platformDirectory(getPlatformByName(platform));
|
||||
|
||||
// Running `pod install` requires `flutter pub get` or `flutter build` to
|
||||
// have been run at some point to create the necessary native build files.
|
||||
// See https://github.com/flutter/flutter/blob/fb7a763c640d247d090cbb373e4b3a0459ac171b/packages/flutter_tools/templates/cocoapods/Podfile-macos#L13-L15
|
||||
// and https://github.com/flutter/flutter/blob/fb7a763c640d247d090cbb373e4b3a0459ac171b/packages/flutter_tools/templates/cocoapods/Podfile-ios-swift#L14-L16
|
||||
final File generatedXCConfig = platform == platformMacOS
|
||||
? platformDir
|
||||
.childDirectory('Flutter')
|
||||
.childDirectory('ephemeral')
|
||||
.childFile('Flutter-Generated.xcconfig')
|
||||
: platformDir
|
||||
.childDirectory('Flutter')
|
||||
.childFile('Generated.xcconfig');
|
||||
if (!generatedXCConfig.existsSync()) {
|
||||
final int exitCode = await processRunner.runAndStream(
|
||||
flutterCommand,
|
||||
<String>['pub', 'get'],
|
||||
workingDir: example.directory,
|
||||
);
|
||||
if (exitCode != 0) {
|
||||
printError('Unable to prepare native project files.');
|
||||
return PackageResult.fail(<String>['Unable to configure project.']);
|
||||
}
|
||||
}
|
||||
|
||||
final int exitCode = await processRunner.runAndStream(
|
||||
'pod',
|
||||
<String>['install'],
|
||||
workingDir: platformDir,
|
||||
environment: <String, String>{
|
||||
'LANG': 'en_US.UTF-8',
|
||||
},
|
||||
);
|
||||
if (exitCode != 0) {
|
||||
printError('Unable to "pod install"');
|
||||
return PackageResult.fail(<String>['Unable to "pod install"']);
|
||||
}
|
||||
}
|
||||
|
||||
return PackageResult.success();
|
||||
}
|
||||
|
||||
Future<bool> _fetchDartPackages(RepositoryPackage package) async {
|
||||
final String command = package.requiresFlutter() ? flutterCommand : 'dart';
|
||||
final int exitCode = await processRunner.runAndStream(
|
||||
command, <String>['pub', 'get'],
|
||||
workingDir: package.directory);
|
||||
return exitCode == 0;
|
||||
}
|
||||
|
||||
bool _hasExampleSupportingRequestedPlatform(RepositoryPackage package) {
|
||||
return package.getExamples().any((RepositoryPackage example) {
|
||||
return _targetPlatforms.any(
|
||||
(FlutterPlatform platform) => example.appSupportsPlatform(platform));
|
||||
});
|
||||
}
|
||||
|
||||
Iterable<FlutterPlatform> get _targetPlatforms => _platforms
|
||||
.where((String platform) => getBoolArg(platform))
|
||||
.map((String platformName) => getPlatformByName(platformName));
|
||||
}
|
||||
|
@ -36,7 +36,142 @@ void main() {
|
||||
CommandRunner<void>('fetch_deps_test', 'Test for $FetchDepsCommand');
|
||||
runner.addCommand(command);
|
||||
});
|
||||
|
||||
group('dart', () {
|
||||
test('runs pub get', () async {
|
||||
final RepositoryPackage plugin = createFakePlugin(
|
||||
'plugin1', packagesDir, platformSupport: <String, PlatformDetails>{
|
||||
platformIOS: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
final List<String> output =
|
||||
await runCapturingPrint(runner, <String>['fetch-deps']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
orderedEquals(<ProcessCall>[
|
||||
ProcessCall(
|
||||
'flutter',
|
||||
const <String>['pub', 'get'],
|
||||
plugin.directory.path,
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(<Matcher>[
|
||||
contains('Running for plugin1'),
|
||||
contains('No issues found!'),
|
||||
]));
|
||||
});
|
||||
|
||||
test('fails if pub get fails', () async {
|
||||
createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformIOS: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
processRunner
|
||||
.mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
|
||||
<FakeProcessInfo>[
|
||||
FakeProcessInfo(MockProcess(exitCode: 1)),
|
||||
];
|
||||
|
||||
Error? commandError;
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps'], errorHandler: (Error e) {
|
||||
commandError = e;
|
||||
});
|
||||
|
||||
expect(commandError, isA<ToolExit>());
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('Failed to "pub get"'),
|
||||
],
|
||||
));
|
||||
});
|
||||
|
||||
test('skips unsupported packages when any platforms are passed',
|
||||
() async {
|
||||
final RepositoryPackage packageWithBoth = createFakePackage(
|
||||
'supports_both', packagesDir, extraFiles: <String>[
|
||||
'example/linux/placeholder',
|
||||
'example/windows/placeholder'
|
||||
]);
|
||||
final RepositoryPackage packageWithOne = createFakePackage(
|
||||
'supports_one', packagesDir,
|
||||
extraFiles: <String>['example/linux/placeholder']);
|
||||
createFakePackage('supports_neither', packagesDir);
|
||||
|
||||
await runCapturingPrint(runner, <String>[
|
||||
'fetch-deps',
|
||||
'--linux',
|
||||
'--windows',
|
||||
'--supporting-target-platforms-only'
|
||||
]);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
orderedEquals(<ProcessCall>[
|
||||
ProcessCall(
|
||||
'dart',
|
||||
const <String>['pub', 'get'],
|
||||
packageWithBoth.path,
|
||||
),
|
||||
ProcessCall(
|
||||
'dart',
|
||||
const <String>['pub', 'get'],
|
||||
packageWithOne.path,
|
||||
),
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('android', () {
|
||||
test('runs pub get before gradlew dependencies', () async {
|
||||
final RepositoryPackage plugin =
|
||||
createFakePlugin('plugin1', packagesDir, extraFiles: <String>[
|
||||
'example/android/gradlew',
|
||||
], platformSupport: <String, PlatformDetails>{
|
||||
platformAndroid: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
final Directory androidDir = plugin
|
||||
.getExamples()
|
||||
.first
|
||||
.platformDirectory(FlutterPlatform.android);
|
||||
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--android']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
orderedEquals(<ProcessCall>[
|
||||
ProcessCall(
|
||||
'flutter',
|
||||
const <String>['pub', 'get'],
|
||||
plugin.directory.path,
|
||||
),
|
||||
ProcessCall(
|
||||
androidDir.childFile('gradlew').path,
|
||||
const <String>['plugin1:dependencies'],
|
||||
androidDir.path,
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(<Matcher>[
|
||||
contains('Running for plugin1'),
|
||||
contains('No issues found!'),
|
||||
]));
|
||||
});
|
||||
|
||||
test('runs gradlew dependencies', () async {
|
||||
final RepositoryPackage plugin =
|
||||
createFakePlugin('plugin1', packagesDir, extraFiles: <String>[
|
||||
@ -50,8 +185,8 @@ void main() {
|
||||
.first
|
||||
.platformDirectory(FlutterPlatform.android);
|
||||
|
||||
final List<String> output =
|
||||
await runCapturingPrint(runner, <String>['fetch-deps']);
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--android']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
@ -89,8 +224,8 @@ void main() {
|
||||
(RepositoryPackage example) =>
|
||||
example.platformDirectory(FlutterPlatform.android));
|
||||
|
||||
final List<String> output =
|
||||
await runCapturingPrint(runner, <String>['fetch-deps']);
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--android']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
@ -123,8 +258,8 @@ void main() {
|
||||
.first
|
||||
.platformDirectory(FlutterPlatform.android);
|
||||
|
||||
final List<String> output =
|
||||
await runCapturingPrint(runner, <String>['fetch-deps']);
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--android']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
@ -164,7 +299,8 @@ void main() {
|
||||
|
||||
Error? commandError;
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps'], errorHandler: (Error e) {
|
||||
runner, <String>['fetch-deps', '--no-dart', '--android'],
|
||||
errorHandler: (Error e) {
|
||||
commandError = e;
|
||||
});
|
||||
|
||||
@ -199,7 +335,8 @@ void main() {
|
||||
|
||||
Error? commandError;
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps'], errorHandler: (Error e) {
|
||||
runner, <String>['fetch-deps', '--no-dart', '--android'],
|
||||
errorHandler: (Error e) {
|
||||
commandError = e;
|
||||
});
|
||||
|
||||
@ -212,41 +349,479 @@ void main() {
|
||||
],
|
||||
));
|
||||
});
|
||||
|
||||
test('skips non-Android plugins', () async {
|
||||
createFakePlugin('plugin1', packagesDir);
|
||||
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--android']);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('Package does not have native Android dependencies.')
|
||||
],
|
||||
));
|
||||
});
|
||||
|
||||
test('skips non-inline plugins', () async {
|
||||
createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformAndroid: const PlatformDetails(PlatformSupport.federated)
|
||||
});
|
||||
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--android']);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('Package does not have native Android dependencies.')
|
||||
],
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
test('skips non-Android plugins', () async {
|
||||
createFakePlugin('plugin1', packagesDir);
|
||||
group('ios', () {
|
||||
test('runs pub get before pod install', () async {
|
||||
final RepositoryPackage plugin =
|
||||
createFakePlugin('plugin1', packagesDir, extraFiles: <String>[
|
||||
'example/ios/Flutter/Generated.xcconfig',
|
||||
], platformSupport: <String, PlatformDetails>{
|
||||
platformIOS: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
final List<String> output =
|
||||
await runCapturingPrint(runner, <String>['fetch-deps']);
|
||||
final Directory iOSDir =
|
||||
plugin.getExamples().first.platformDirectory(FlutterPlatform.ios);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains(
|
||||
'SKIPPING: Plugin does not have an Android implementation.')
|
||||
final List<String> output =
|
||||
await runCapturingPrint(runner, <String>['fetch-deps', '--ios']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
orderedEquals(<ProcessCall>[
|
||||
const ProcessCall(
|
||||
'flutter',
|
||||
<String>['precache', '--ios'],
|
||||
null,
|
||||
),
|
||||
ProcessCall(
|
||||
'flutter',
|
||||
const <String>['pub', 'get'],
|
||||
plugin.directory.path,
|
||||
),
|
||||
ProcessCall(
|
||||
'pod',
|
||||
const <String>['install'],
|
||||
iOSDir.path,
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(<Matcher>[
|
||||
contains('Running for plugin1'),
|
||||
contains('No issues found!'),
|
||||
]));
|
||||
});
|
||||
|
||||
test('runs on all examples', () async {
|
||||
final List<String> examples = <String>['example1', 'example2'];
|
||||
final RepositoryPackage plugin = createFakePlugin(
|
||||
'plugin1', packagesDir,
|
||||
examples: examples,
|
||||
extraFiles: <String>[
|
||||
'example/example1/ios/Flutter/Generated.xcconfig',
|
||||
'example/example2/ios/Flutter/Generated.xcconfig',
|
||||
],
|
||||
));
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformIOS: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
final Iterable<Directory> exampleIOSDirs = plugin.getExamples().map(
|
||||
(RepositoryPackage example) =>
|
||||
example.platformDirectory(FlutterPlatform.ios));
|
||||
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--ios']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
orderedEquals(<ProcessCall>[
|
||||
const ProcessCall(
|
||||
'flutter',
|
||||
<String>['precache', '--ios'],
|
||||
null,
|
||||
),
|
||||
for (final Directory directory in exampleIOSDirs)
|
||||
ProcessCall(
|
||||
'pod',
|
||||
const <String>['install'],
|
||||
directory.path,
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(<Matcher>[
|
||||
contains('Running for plugin1'),
|
||||
contains('No issues found!'),
|
||||
]));
|
||||
});
|
||||
|
||||
test('runs pub get if example is not configured', () async {
|
||||
final RepositoryPackage plugin = createFakePlugin(
|
||||
'plugin1', packagesDir, platformSupport: <String, PlatformDetails>{
|
||||
platformIOS: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
final RepositoryPackage example = plugin.getExamples().first;
|
||||
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--ios']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
orderedEquals(<ProcessCall>[
|
||||
const ProcessCall(
|
||||
'flutter',
|
||||
<String>['precache', '--ios'],
|
||||
null,
|
||||
),
|
||||
ProcessCall(
|
||||
'flutter',
|
||||
const <String>['pub', 'get'],
|
||||
example.directory.path,
|
||||
),
|
||||
ProcessCall(
|
||||
'pod',
|
||||
const <String>['install'],
|
||||
example.platformDirectory(FlutterPlatform.ios).path,
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(<Matcher>[
|
||||
contains('Running for plugin1'),
|
||||
contains('No issues found!'),
|
||||
]));
|
||||
});
|
||||
|
||||
test('fails if pre-pod pub get fails', () async {
|
||||
createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformIOS: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
processRunner
|
||||
.mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
|
||||
<FakeProcessInfo>[
|
||||
FakeProcessInfo(MockProcess(), <String>['precache']),
|
||||
FakeProcessInfo(MockProcess(exitCode: 1), <String>['pub', 'get']),
|
||||
];
|
||||
|
||||
Error? commandError;
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--ios'],
|
||||
errorHandler: (Error e) {
|
||||
commandError = e;
|
||||
});
|
||||
|
||||
expect(commandError, isA<ToolExit>());
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('Unable to configure project'),
|
||||
],
|
||||
));
|
||||
});
|
||||
|
||||
test('fails if pod install fails', () async {
|
||||
createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformIOS: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
processRunner.mockProcessesForExecutable['pod'] = <FakeProcessInfo>[
|
||||
FakeProcessInfo(MockProcess(exitCode: 1)),
|
||||
];
|
||||
|
||||
Error? commandError;
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--ios'],
|
||||
errorHandler: (Error e) {
|
||||
commandError = e;
|
||||
});
|
||||
|
||||
expect(commandError, isA<ToolExit>());
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('The following packages had errors:'),
|
||||
],
|
||||
));
|
||||
});
|
||||
|
||||
test('skips non-iOS plugins', () async {
|
||||
createFakePlugin('plugin1', packagesDir);
|
||||
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--ios']);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('Package does not have native iOS dependencies.')
|
||||
],
|
||||
));
|
||||
});
|
||||
|
||||
test('skips non-inline plugins', () async {
|
||||
createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformIOS: const PlatformDetails(PlatformSupport.federated)
|
||||
});
|
||||
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--ios']);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('Package does not have native iOS dependencies.')
|
||||
],
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
test('skips non-inline plugins', () async {
|
||||
createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformAndroid: const PlatformDetails(PlatformSupport.federated)
|
||||
});
|
||||
group('macos', () {
|
||||
test('runs pub get before pod install', () async {
|
||||
final RepositoryPackage plugin =
|
||||
createFakePlugin('plugin1', packagesDir, extraFiles: <String>[
|
||||
'example/macos/Flutter/ephemeral/Flutter-Generated.xcconfig',
|
||||
], platformSupport: <String, PlatformDetails>{
|
||||
platformMacOS: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
final List<String> output =
|
||||
await runCapturingPrint(runner, <String>['fetch-deps']);
|
||||
final Directory macOSDir =
|
||||
plugin.getExamples().first.platformDirectory(FlutterPlatform.macos);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains(
|
||||
'SKIPPING: Plugin does not have an Android implementation.')
|
||||
final List<String> output =
|
||||
await runCapturingPrint(runner, <String>['fetch-deps', '--macos']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
orderedEquals(<ProcessCall>[
|
||||
const ProcessCall(
|
||||
'flutter',
|
||||
<String>['precache', '--macos'],
|
||||
null,
|
||||
),
|
||||
ProcessCall(
|
||||
'flutter',
|
||||
const <String>['pub', 'get'],
|
||||
plugin.directory.path,
|
||||
),
|
||||
ProcessCall(
|
||||
'pod',
|
||||
const <String>['install'],
|
||||
macOSDir.path,
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(<Matcher>[
|
||||
contains('Running for plugin1'),
|
||||
contains('No issues found!'),
|
||||
]));
|
||||
});
|
||||
|
||||
test('runs on all examples', () async {
|
||||
final List<String> examples = <String>['example1', 'example2'];
|
||||
final RepositoryPackage plugin = createFakePlugin(
|
||||
'plugin1', packagesDir,
|
||||
examples: examples,
|
||||
extraFiles: <String>[
|
||||
'example/example1/macos/Flutter/ephemeral/Flutter-Generated.xcconfig',
|
||||
'example/example2/macos/Flutter/ephemeral/Flutter-Generated.xcconfig',
|
||||
],
|
||||
));
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformMacOS: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
final Iterable<Directory> examplemacOSDirs = plugin.getExamples().map(
|
||||
(RepositoryPackage example) =>
|
||||
example.platformDirectory(FlutterPlatform.macos));
|
||||
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--macos']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
orderedEquals(<ProcessCall>[
|
||||
const ProcessCall(
|
||||
'flutter',
|
||||
<String>['precache', '--macos'],
|
||||
null,
|
||||
),
|
||||
for (final Directory directory in examplemacOSDirs)
|
||||
ProcessCall(
|
||||
'pod',
|
||||
const <String>['install'],
|
||||
directory.path,
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(<Matcher>[
|
||||
contains('Running for plugin1'),
|
||||
contains('No issues found!'),
|
||||
]));
|
||||
});
|
||||
|
||||
test('runs pub get if example is not configured', () async {
|
||||
final RepositoryPackage plugin = createFakePlugin(
|
||||
'plugin1', packagesDir, platformSupport: <String, PlatformDetails>{
|
||||
platformMacOS: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
final RepositoryPackage example = plugin.getExamples().first;
|
||||
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--macos']);
|
||||
|
||||
expect(
|
||||
processRunner.recordedCalls,
|
||||
orderedEquals(<ProcessCall>[
|
||||
const ProcessCall(
|
||||
'flutter',
|
||||
<String>['precache', '--macos'],
|
||||
null,
|
||||
),
|
||||
ProcessCall(
|
||||
'flutter',
|
||||
const <String>['pub', 'get'],
|
||||
example.directory.path,
|
||||
),
|
||||
ProcessCall(
|
||||
'pod',
|
||||
const <String>['install'],
|
||||
example.platformDirectory(FlutterPlatform.macos).path,
|
||||
),
|
||||
]),
|
||||
);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(<Matcher>[
|
||||
contains('Running for plugin1'),
|
||||
contains('No issues found!'),
|
||||
]));
|
||||
});
|
||||
|
||||
test('fails if pre-pod pub get fails', () async {
|
||||
createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformMacOS: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
processRunner
|
||||
.mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
|
||||
<FakeProcessInfo>[
|
||||
FakeProcessInfo(MockProcess(), <String>['precache']),
|
||||
FakeProcessInfo(MockProcess(exitCode: 1), <String>['pub', 'get']),
|
||||
];
|
||||
|
||||
Error? commandError;
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--macos'],
|
||||
errorHandler: (Error e) {
|
||||
commandError = e;
|
||||
});
|
||||
|
||||
expect(commandError, isA<ToolExit>());
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('Unable to configure project'),
|
||||
],
|
||||
));
|
||||
});
|
||||
|
||||
test('fails if pod install fails', () async {
|
||||
createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformMacOS: const PlatformDetails(PlatformSupport.inline)
|
||||
});
|
||||
|
||||
processRunner.mockProcessesForExecutable['pod'] = <FakeProcessInfo>[
|
||||
FakeProcessInfo(MockProcess(exitCode: 1)),
|
||||
];
|
||||
|
||||
Error? commandError;
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--macos'],
|
||||
errorHandler: (Error e) {
|
||||
commandError = e;
|
||||
});
|
||||
|
||||
expect(commandError, isA<ToolExit>());
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('The following packages had errors:'),
|
||||
],
|
||||
));
|
||||
});
|
||||
|
||||
test('skips non-macOS plugins', () async {
|
||||
createFakePlugin('plugin1', packagesDir);
|
||||
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--macos']);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('Package does not have native macOS dependencies.')
|
||||
],
|
||||
));
|
||||
});
|
||||
|
||||
test('skips non-inline plugins', () async {
|
||||
createFakePlugin('plugin1', packagesDir,
|
||||
platformSupport: <String, PlatformDetails>{
|
||||
platformMacOS: const PlatformDetails(PlatformSupport.federated)
|
||||
});
|
||||
|
||||
final List<String> output = await runCapturingPrint(
|
||||
runner, <String>['fetch-deps', '--no-dart', '--macos']);
|
||||
|
||||
expect(
|
||||
output,
|
||||
containsAllInOrder(
|
||||
<Matcher>[
|
||||
contains('Package does not have native macOS dependencies.')
|
||||
],
|
||||
));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -394,6 +394,7 @@ class RecordingProcessRunner extends ProcessRunner {
|
||||
String executable,
|
||||
List<String> args, {
|
||||
Directory? workingDir,
|
||||
Map<String, String>? environment,
|
||||
bool exitOnError = false,
|
||||
}) async {
|
||||
recordedCalls.add(ProcessCall(executable, args, workingDir?.path));
|
||||
@ -412,6 +413,7 @@ class RecordingProcessRunner extends ProcessRunner {
|
||||
String executable,
|
||||
List<String> args, {
|
||||
Directory? workingDir,
|
||||
Map<String, String>? environment,
|
||||
bool exitOnError = false,
|
||||
bool logOnError = false,
|
||||
Encoding stdoutEncoding = io.systemEncoding,
|
||||
|
Reference in New Issue
Block a user