diff --git a/CHANGELOG.md b/CHANGELOG.md index 635c816..12e5f73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## Version 0.19.0 +- introduces `force-use-flutter` option for all commands to force dart_apitool to use the `flutter` command. + ## Version 0.18.0 - add missing export to json output for `extract` command - adds analysis of readability and writability of fields. diff --git a/README.md b/README.md index dd1a4e8..ee43f70 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,10 @@ Usage: dart-apitool extract [arguments] --[no-]remove-example Removes examples from the package to analyze. (defaults to on) --[no-]set-exit-on-missing-export Sets exit code to != 0 if missing exports are detected in the API. + --force-use-flutter If present forces dart_apitool to use Flutter + (instead of Dart if the project is Dart only) + +Run "dart-apitool help" to see global options. ``` ### diff @@ -91,10 +95,15 @@ Usage: dart-apitool diff [arguments] [none, allowAdding (default), strict] --[no-]remove-example Removes examples from the package to analyze. (defaults to on) - --[no-]ignore-requiredness Whether to ignore the required aspect of interfaces (yielding less strict version bump requirements) + --[no-]ignore-requiredness Whether to ignore the required aspect of interfaces + (yielding less strict version bump requirements) --report-format Which output format should be used [cli (default), markdown, json] --report-file-path Where to store the report file (no effect on cli option) + --force-use-flutter If present forces dart_apitool to use Flutter + (instead of Dart if the project is Dart only) + +Run "dart-apitool help" to see global options. ``` ## Integration diff --git a/lib/src/cli/commands/command_mixin.dart b/lib/src/cli/commands/command_mixin.dart index 5a0ec4f..1afa88b 100644 --- a/lib/src/cli/commands/command_mixin.dart +++ b/lib/src/cli/commands/command_mixin.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:args/args.dart'; import 'package:dart_apitool/api_tool.dart'; import 'package:dart_apitool/src/cli/source_item.dart'; import 'package:path/path.dart' as p; @@ -22,17 +23,41 @@ Package reference can be one of: OBSOLETE: Has no effect anymore. '''; + static final String _flagNameForceUseFlutter = 'force-use-flutter'; + static final String _helpTextForceUseFlutter = + 'If present forces dart_apitool to use Flutter\n(instead of Dart if the project is Dart only)'; + + void init(ArgParser argParser) { + argParser.addFlag( + _flagNameForceUseFlutter, + help: _helpTextForceUseFlutter, + defaultsTo: false, + negatable: false, + ); + } + /// prepares given [ref]. Depending on the type of ref this can include /// - copying the package to a temporary directory /// - running pub get /// If you use [analyze] with this result then it will take care to clean up /// everything (e.g. removing temp directory) - Future prepare(PackageRef ref) async { + Future prepare( + ArgResults argResults, + PackageRef ref, + ) async { final stdoutSession = StdoutSession(); + + final forceUseFlutterTool = + (argResults[_flagNameForceUseFlutter] as bool?) ?? false; + List sources = []; String? packageRelativePath; if (ref.isDirectoryPath) { - await stdoutSession.writeln('Preparing ${ref.ref}'); + String forceUseFlutterSuffix = ''; + if (forceUseFlutterTool) { + forceUseFlutterSuffix = ' (forced Flutter)'; + } + await stdoutSession.writeln('Preparing ${ref.ref}$forceUseFlutterSuffix'); String sourceDir = ref.ref; if (sourceDir.endsWith(p.separator)) { sourceDir = @@ -70,10 +95,18 @@ OBSOLETE: Has no effect anymore. await _copyPath(sourceItem.sourceDir, sourceItem.destinationPath(forPrefix: tempDir.path)); if (!sourceItem.isInCache) { + String forceUseFlutterSuffix = ''; + if (forceUseFlutterTool) { + forceUseFlutterSuffix = ' (forced Flutter)'; + } + await stdoutSession.writeln( - 'Preparing package dependencies for local package ${sourceItem.sourceDir}'); - await PubInteraction.runPubGet(sourceItem.sourceDir, - stdoutSession: stdoutSession); + 'Preparing package dependencies for local package ${sourceItem.sourceDir}$forceUseFlutterSuffix'); + await PubInteraction.runPubGet( + sourceItem.sourceDir, + stdoutSession: stdoutSession, + forceUseFlutterTool: forceUseFlutterTool, + ); final sourcePackageConfig = File(_getPackageConfigPathForPackage(sourceItem.sourceDir)); final targetPackageConfig = @@ -106,11 +139,16 @@ OBSOLETE: Has no effect anymore. /// [doMergeBaseClasses] defines if base classes should be merged into derived ones. This allows to remove private base classes from the list of interface declarations. /// [doAnalyzePlatformConstraints] defines if the platform constraints of the package shall be analyzed. Future analyze( + ArgResults argResults, PreparedPackageRef preparedRef, { bool doAnalyzePlatformConstraints = true, bool doRemoveExample = true, }) async { final stdoutSession = StdoutSession(); + + final forceUseFlutterTool = + (argResults[_flagNameForceUseFlutter] as bool?) ?? false; + String? path; if (preparedRef.packageRef.isDirectoryPath) { path = preparedRef.packageRef.ref; @@ -141,7 +179,11 @@ OBSOLETE: Has no effect anymore. final packageConfig = File(_getPackageConfigPathForPackage(packagePath)); if (!packageConfig.existsSync()) { await stdoutSession.writeln('Running pub get'); - await PubInteraction.runPubGet(packagePath, stdoutSession: stdoutSession); + await PubInteraction.runPubGet( + packagePath, + stdoutSession: stdoutSession, + forceUseFlutterTool: forceUseFlutterTool, + ); } else { await stdoutSession .writeln('Omitting pub get (package config already present)'); diff --git a/lib/src/cli/commands/diff_command.dart b/lib/src/cli/commands/diff_command.dart index e874160..1b1d777 100644 --- a/lib/src/cli/commands/diff_command.dart +++ b/lib/src/cli/commands/diff_command.dart @@ -97,8 +97,10 @@ You may want to do this if you want to make sure ); argParser.addFlag( _optionNameIgnoreRequiredness, - help: - 'Whether to ignore the required aspect of interfaces (yielding less strict version bump requirements)', + help: ''' +Whether to ignore the required aspect of interfaces +(yielding less strict version bump requirements) +''', defaultsTo: false, negatable: true, ); @@ -114,6 +116,7 @@ You may want to do this if you want to make sure help: 'Where to store the report file (no effect on cli option)', mandatory: false, ); + init(argParser); } @override @@ -150,18 +153,22 @@ You may want to do this if you want to make sure argResults![_optionNameIgnoreRequiredness] as bool; final preparedOldPackageRef = await prepare( + argResults!, oldPackageRef, ); final preparedNewPackageRef = await prepare( + argResults!, newPackageRef, ); final oldPackageApi = await analyze( + argResults!, preparedOldPackageRef, doAnalyzePlatformConstraints: !noAnalyzePlatformConstraints, doRemoveExample: doRemoveExample, ); final newPackageApi = await analyze( + argResults!, preparedNewPackageRef, doAnalyzePlatformConstraints: !noAnalyzePlatformConstraints, doRemoveExample: doRemoveExample, diff --git a/lib/src/cli/commands/extract_command.dart b/lib/src/cli/commands/extract_command.dart index 62e833c..ccce9de 100644 --- a/lib/src/cli/commands/extract_command.dart +++ b/lib/src/cli/commands/extract_command.dart @@ -60,6 +60,7 @@ If not specified the extracted API will be printed to the console. defaultsTo: false, negatable: true, ); + init(argParser); } @override @@ -72,9 +73,11 @@ If not specified the extracted API will be printed to the console. argResults![_optionNameSetExitCodeOnMissingExport] as bool; final preparedPackageRef = await prepare( + argResults!, packageRef, ); final packageApi = await analyze( + argResults!, preparedPackageRef, doAnalyzePlatformConstraints: !noAnalyzePlatformConstraints, doRemoveExample: doRemoveExample, diff --git a/lib/src/tooling/dart_interaction.dart b/lib/src/tooling/dart_interaction.dart index 041c38f..38d5ba2 100644 --- a/lib/src/tooling/dart_interaction.dart +++ b/lib/src/tooling/dart_interaction.dart @@ -11,22 +11,35 @@ import '../utils/utils.dart'; /// Helper class for interacting with Dart and Flutter abstract class DartInteraction { /// runs the dart or flutter command with the given [args]. - /// The decision which command to run is taken from the pubspeck.yaml file in + /// The decision which command to run is taken from the pubspec.yaml file in /// [forDirectory] + /// This command determines which tool to use based on the pubspec.yaml file. + /// If [forceUseFlutterTool] is given then this value will be used to + /// determine which tool to use. [true] means Flutter, [false] means Dart static Future runDartOrFlutterCommand( String forDirectory, { List args = const [], StdoutSession? stdoutSession, + bool forceUseFlutterTool = false, }) async { - final pubspecPath = path.join(forDirectory, 'pubspec.yaml'); - final pubspecExists = await File(pubspecPath).exists(); - if (!pubspecExists) { - throw RunDartError( - 'Error running pub get in $forDirectory:\nThis is not a valid dart package directory'); + bool useFlutter = false; + if (!forceUseFlutterTool) { + // if we are not forced to use Flutter then we get this information + // from the pubspec.yaml file + final pubspecPath = path.join(forDirectory, 'pubspec.yaml'); + final pubspecExists = await File(pubspecPath).exists(); + if (!pubspecExists) { + throw RunDartError( + 'Error running pub get in $forDirectory:\nThis is not a valid dart package directory'); + } + final yamlContent = await File(pubspecPath).readAsString(); + final pubSpec = Pubspec.parse(yamlContent); + useFlutter = pubSpec.dependencies.containsKey('flutter'); + } else { + // here we are forced to use Flutter (forceUseFlutterTool == true) + useFlutter = true; } - final yamlContent = await File(pubspecPath).readAsString(); - final pubSpec = Pubspec.parse(yamlContent); - if (!pubSpec.dependencies.containsKey('flutter')) { + if (!useFlutter) { return _runDartOrFlutterCommand( _getDartExecutablePath(), workingDirectory: forDirectory, diff --git a/lib/src/tooling/pub_interaction.dart b/lib/src/tooling/pub_interaction.dart index 3daa7f6..935b6ea 100644 --- a/lib/src/tooling/pub_interaction.dart +++ b/lib/src/tooling/pub_interaction.dart @@ -111,6 +111,7 @@ abstract class PubInteraction { static Future runPubGet( String packageDirectory, { StdoutSession? stdoutSession, + bool forceUseFlutterTool = false, }) async { return DartInteraction.runDartOrFlutterCommand( packageDirectory, @@ -119,6 +120,7 @@ abstract class PubInteraction { 'get', ], stdoutSession: stdoutSession, + forceUseFlutterTool: forceUseFlutterTool, ); } } diff --git a/pubspec.yaml b/pubspec.yaml index 41e5eb5..f75e89a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: dart_apitool description: A tool to analyze the public API of a package, create a model of it and diff it against another version to check semver. repository: https://github.com/bmw-tech/dart_apitool -version: 0.18.1-dev +version: 0.19.0-dev environment: sdk: ">=3.0.0 <4.0.0"