Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions script/tool/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 0.14.2

* Ensures that pub commands use `flutter` or `dart` depending on whether the
package requires Flutter for analysis and publishing, to support
non-Flutter-based repositories.
* Adds `--skip-if-not-supporting-dart-version` to support package constraints
via Dart versions rather than Flutter versions.

## 0.14.1

* Adds `min_dart` as an alternative to `min_flutter` in tool configuration.
Expand Down
12 changes: 7 additions & 5 deletions script/tool/lib/src/analyze_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'common/gradle.dart';
import 'common/output_utils.dart';
import 'common/package_looping_command.dart';
import 'common/plugin_utils.dart';
import 'common/pub_utils.dart';
import 'common/repository_package.dart';
import 'common/xcode.dart';

Expand Down Expand Up @@ -357,12 +358,13 @@ class AnalyzeCommand extends PackageLoopingCommand {
}

Future<bool> _runPubCommand(RepositoryPackage package, String command) async {
Comment thread
stuartmorgan-g marked this conversation as resolved.
final int exitCode = await processRunner.runAndStream(
flutterCommand,
<String>['pub', command],
workingDir: package.directory,
return runPubCommand(
<String>[command],
package,
processRunner,
platform,
dartSdkPathOverride: _dartBinaryPath,
);
return exitCode == 0;
}

/// Runs Gradle lint analysis for the given package, and returns the result
Expand Down
21 changes: 18 additions & 3 deletions script/tool/lib/src/common/package_looping_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,20 @@ abstract class PackageLoopingCommand extends PackageCommand {
'the provided version, or a Dart version newer than the '
'corresponding Dart version.',
);
argParser.addOption(
_skipByDartVersionArg,
help:
'Skip any packages that require a Dart version newer than the '
'provided version.',
);
}

static const String _skipByFlutterVersionArg =
'skip-if-not-supporting-flutter-version';

static const String _skipByDartVersionArg =
'skip-if-not-supporting-dart-version';

/// Packages that had at least one [logWarning] call.
final Set<PackageEnumerationEntry> _packagesWithWarnings =
<PackageEnumerationEntry>{};
Expand Down Expand Up @@ -289,9 +298,15 @@ abstract class PackageLoopingCommand extends PackageCommand {
final Version? minFlutterVersion = minFlutterVersionArg.isEmpty
? null
: Version.parse(minFlutterVersionArg);
final Version? minDartVersion = minFlutterVersion == null
? null
: getDartSdkForFlutterSdk(minFlutterVersion);

// Use the explicit Dart min if provided, otherwise fall back to the
// version corresponding to the Flutter min if that was provided.
final String minDartVersionArg = getStringArg(_skipByDartVersionArg);
final Version? minDartVersion = minDartVersionArg.isNotEmpty
? Version.parse(minDartVersionArg)
: (minFlutterVersion == null
? null
: getDartSdkForFlutterSdk(minFlutterVersion));

final runStart = DateTime.now();

Expand Down
68 changes: 56 additions & 12 deletions script/tool/lib/src/common/pub_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,42 @@ import 'repository_package.dart';
/// Runs either `dart pub get` or `flutter pub get` in [package], depending on
/// the package type.
///
/// If [alwaysUseFlutter] is true, it will use `flutter pub get` regardless.
/// This can be useful, for instance, to get the `flutter`-default behavior
/// of fetching example packages as well.
///
/// If [streamOutput] is false, output will only be printed if the command
/// fails.
Future<bool> runPubGet(
RepositoryPackage package,
ProcessRunner processRunner,
Platform platform, {
bool alwaysUseFlutter = false,
Comment thread
chunhtai marked this conversation as resolved.
bool streamOutput = true,
}) async {
// Running `dart pub get` on a Flutter package can fail if a non-Flutter Dart
// is first in the path, so use `flutter pub get` for any Flutter package.
final bool useFlutter = alwaysUseFlutter || package.requiresFlutter();
final command = useFlutter
? (platform.isWindows ? 'flutter.bat' : 'flutter')
: 'dart';
final args = <String>['pub', 'get'];
return runPubCommand(
<String>['get'],
package,
processRunner,
platform,
streamOutput: streamOutput,
);
}

/// Runs a pub command with the given arguments in [package],
/// using either 'dart' or 'flutter' depending on the package type.
///
/// If [streamOutput] is false, output will only be printed if the command
/// fails.
Future<bool> runPubCommand(
List<String> commandArgs,
RepositoryPackage package,
ProcessRunner processRunner,
Platform platform, {
bool streamOutput = true,
String? dartSdkPathOverride,
}) async {
final String command = _pubCommand(
package,
platform,
dartSdkPathOverride: dartSdkPathOverride,
);
final args = <String>['pub', ...commandArgs];
final int exitCode;
if (streamOutput) {
exitCode = await processRunner.runAndStream(
Expand All @@ -53,3 +68,32 @@ Future<bool> runPubGet(
}
return exitCode == 0;
}

/// Starts a pub command with the given arguments in [package],
/// using either 'dart' or 'flutter' depending on the package type, and returns
/// a process that can be used to wait for completion and stream output.
///
/// If no output capturing is necessary, prefer [runPubCommand].
Future<io.Process> startPubCommand(
List<String> commandArgs,
RepositoryPackage package,
ProcessRunner processRunner,
Platform platform,
) async {
return processRunner.start(_pubCommand(package, platform), <String>[
'pub',
...commandArgs,
], workingDirectory: package.directory);
}

String _pubCommand(
RepositoryPackage package,
Platform platform, {
String? dartSdkPathOverride,
}) {
// Running `dart pub get` on a Flutter package can fail if a non-Flutter Dart
// is first in the path, so use `flutter pub get` for any Flutter package.
return package.requiresFlutter()
? (platform.isWindows ? 'flutter.bat' : 'flutter')
: (dartSdkPathOverride ?? 'dart');
}
9 changes: 5 additions & 4 deletions script/tool/lib/src/publish_check_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,11 @@ class PublishCheckCommand extends PackageLoopingCommand {
await _fetchExampleDeps(package);

print('Running pub publish --dry-run:');
final io.Process process = await processRunner.start(
flutterCommand,
<String>['pub', 'publish', '--', '--dry-run'],
workingDirectory: package.directory,
final io.Process process = await startPubCommand(
<String>['publish', '--dry-run'],
package,
processRunner,
platform,
);

final outputBuffer = StringBuffer();
Expand Down
9 changes: 5 additions & 4 deletions script/tool/lib/src/publish_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -477,10 +477,11 @@ Safe to ignore if the package is deleted in this commit.
_ensureValidPubCredential();
}

final io.Process publish = await processRunner.start(
flutterCommand,
<String>['pub', 'publish', ..._publishFlags],
workingDirectory: package.directory,
final io.Process publish = await startPubCommand(
<String>['publish', ..._publishFlags],
package,
processRunner,
platform,
);
publish.stdout.transform(utf8.decoder).listen((String data) => print(data));
publish.stderr.transform(utf8.decoder).listen((String data) => print(data));
Expand Down
2 changes: 1 addition & 1 deletion script/tool/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: flutter_plugin_tools
description: Productivity and CI utils for Flutter team package repositories.
repository: https://github.com/flutter/packages/tree/main/script/tool
version: 0.14.1
version: 0.14.2

dependencies:
args: ^2.1.0
Expand Down
32 changes: 11 additions & 21 deletions script/tool/test/analyze_command_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ void main() {

group('dart analyze', () {
test('analyzes all packages', () async {
// Create a non-Flutter Dart package and a Flutter plugin to make sure
// the right command is used for each.
final RepositoryPackage package1 = createFakePackage('a', packagesDir);
final RepositoryPackage plugin2 = createFakePlugin('b', packagesDir);

Expand All @@ -144,7 +146,7 @@ void main() {
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall('flutter', const <String>['pub', 'get'], package1.path),
ProcessCall('dart', const <String>['pub', 'get'], package1.path),
ProcessCall('dart', const <String>[
'analyze',
'--fatal-infos',
Expand All @@ -158,7 +160,7 @@ void main() {
);
});

test('skips flutter pub get for examples', () async {
test('skips pub get for examples', () async {
final RepositoryPackage plugin1 = createFakePlugin('a', packagesDir);

await runCapturingPrint(runner, <String>['analyze']);
Expand All @@ -175,7 +177,7 @@ void main() {
);
});

test('runs flutter pub get for non-example subpackages', () async {
test('runs pub get for non-example subpackages', () async {
final RepositoryPackage mainPackage = createFakePackage('a', packagesDir);
final Directory otherPackagesDir = mainPackage.directory.childDirectory(
'other_packages',
Expand All @@ -194,18 +196,9 @@ void main() {
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall('flutter', const <String>[
'pub',
'get',
], mainPackage.path),
ProcessCall('flutter', const <String>[
'pub',
'get',
], subpackage1.path),
ProcessCall('flutter', const <String>[
'pub',
'get',
], subpackage2.path),
ProcessCall('dart', const <String>['pub', 'get'], mainPackage.path),
ProcessCall('dart', const <String>['pub', 'get'], subpackage1.path),
ProcessCall('dart', const <String>['pub', 'get'], subpackage2.path),
ProcessCall('dart', const <String>[
'analyze',
'--fatal-infos',
Expand All @@ -225,7 +218,7 @@ void main() {
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall('flutter', const <String>['pub', 'get'], package.path),
ProcessCall('dart', const <String>['pub', 'get'], package.path),
ProcessCall('dart', const <String>[
'analyze',
'--fatal-infos',
Expand Down Expand Up @@ -255,7 +248,7 @@ void main() {
});

test(
'does not run flutter pub get for non-example subpackages with --lib-only',
'does not run pub get for non-example subpackages with --lib-only',
() async {
final RepositoryPackage mainPackage = createFakePackage(
'a',
Expand All @@ -272,10 +265,7 @@ void main() {
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall('flutter', const <String>[
'pub',
'get',
], mainPackage.path),
ProcessCall('dart', const <String>['pub', 'get'], mainPackage.path),
ProcessCall('dart', const <String>[
'analyze',
'--fatal-infos',
Expand Down
50 changes: 46 additions & 4 deletions script/tool/test/common/package_looping_command_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,51 @@ skip/b
);
});

test('skips unsupported Dart versions when requested', () async {
test(
'skips unsupported Dart versions when requested implicitly by Flutter version',
() async {
final RepositoryPackage excluded = createFakePackage(
'excluded_package',
packagesDir,
dartConstraint: '>=2.18.0 <4.0.0',
);
final RepositoryPackage included = createFakePackage(
'a_package',
packagesDir,
);

final TestPackageLoopingCommand command = createTestCommand(
packageLoopingType: PackageLoopingType.includeAllSubpackages,
hasLongOutput: false,
);
final List<String> output = await runCommand(
command,
arguments: <String>[
'--skip-if-not-supporting-flutter-version=3.0.0', // Flutter 3.0.0 -> Dart 2.17.0
],
);

expect(
command.checkedPackages,
unorderedEquals(<String>[
included.path,
getExampleDir(included).path,
]),
);
expect(command.checkedPackages, isNot(contains(excluded.path)));

expect(
output,
containsAllInOrder(<String>[
'${_startHeadingColor}Running for a_package...$_endColor',
'${_startHeadingColor}Running for excluded_package...$_endColor',
'$_startSkipColor SKIPPING: Does not support Dart 2.17.0$_endColor',
]),
);
},
);

test('skips unsupported Dart versions when requested explicitly', () async {
final RepositoryPackage excluded = createFakePackage(
'excluded_package',
packagesDir,
Expand All @@ -518,9 +562,7 @@ skip/b
);
final List<String> output = await runCommand(
command,
arguments: <String>[
'--skip-if-not-supporting-flutter-version=3.0.0', // Flutter 3.0.0 -> Dart 2.17.0
],
arguments: <String>['--skip-if-not-supporting-dart-version=2.17.0'],
);

expect(
Expand Down
17 changes: 0 additions & 17 deletions script/tool/test/common/pub_utils_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,23 +53,6 @@ void main() {
);
});

test('runs with Flutter for a Dart package when requested', () async {
final RepositoryPackage package = createFakePackage(
'a_package',
packagesDir,
);
final platform = MockPlatform();

await runPubGet(package, processRunner, platform, alwaysUseFlutter: true);

expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall('flutter', const <String>['pub', 'get'], package.path),
]),
);
});

test('uses the correct Flutter command on Windows', () async {
final RepositoryPackage package = createFakePackage(
'a_package',
Expand Down
Loading
Loading