| // Copyright 2013 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 'dart:io'; |
| |
| import 'package:file/file.dart'; |
| import 'package:path/path.dart' as p; |
| import 'package:platform/platform.dart'; |
| |
| import 'common/core.dart'; |
| import 'common/package_looping_command.dart'; |
| import 'common/process_runner.dart'; |
| import 'common/repository_package.dart'; |
| |
| const int _exitUnsupportedPlatform = 2; |
| const int _exitPodNotInstalled = 3; |
| |
| /// Lint the CocoaPod podspecs and run unit tests. |
| /// |
| /// See https://guides.cocoapods.org/terminal/commands.html#pod_lib_lint. |
| class LintPodspecsCommand extends PackageLoopingCommand { |
| /// Creates an instance of the linter command. |
| LintPodspecsCommand( |
| Directory packagesDir, { |
| ProcessRunner processRunner = const ProcessRunner(), |
| Platform platform = const LocalPlatform(), |
| }) : super(packagesDir, processRunner: processRunner, platform: platform); |
| |
| @override |
| final String name = 'podspecs'; |
| |
| @override |
| List<String> get aliases => <String>['podspec']; |
| |
| @override |
| final String description = |
| 'Runs "pod lib lint" on all iOS and macOS plugin podspecs.\n\n' |
| 'This command requires "pod" and "flutter" to be in your path. Runs on macOS only.'; |
| |
| @override |
| Future<void> initializeRun() async { |
| if (!platform.isMacOS) { |
| printError('This command is only supported on macOS'); |
| throw ToolExit(_exitUnsupportedPlatform); |
| } |
| |
| final ProcessResult result = await processRunner.run( |
| 'which', |
| <String>['pod'], |
| workingDir: packagesDir, |
| logOnError: true, |
| ); |
| if (result.exitCode != 0) { |
| printError('Unable to find "pod". Make sure it is in your path.'); |
| throw ToolExit(_exitPodNotInstalled); |
| } |
| } |
| |
| @override |
| Future<PackageResult> runForPackage(RepositoryPackage package) async { |
| final List<String> errors = <String>[]; |
| |
| final List<File> podspecs = await _podspecsToLint(package); |
| if (podspecs.isEmpty) { |
| return PackageResult.skip('No podspecs.'); |
| } |
| |
| for (final File podspec in podspecs) { |
| if (!await _lintPodspec(podspec)) { |
| errors.add(p.basename(podspec.path)); |
| } |
| } |
| return errors.isEmpty |
| ? PackageResult.success() |
| : PackageResult.fail(errors); |
| } |
| |
| Future<List<File>> _podspecsToLint(RepositoryPackage package) async { |
| final List<File> podspecs = |
| await getFilesForPackage(package).where((File entity) { |
| final String filePath = entity.path; |
| return path.extension(filePath) == '.podspec'; |
| }).toList(); |
| |
| podspecs.sort((File a, File b) => a.basename.compareTo(b.basename)); |
| return podspecs; |
| } |
| |
| Future<bool> _lintPodspec(File podspec) async { |
| // Do not run the static analyzer on plugins with known analyzer issues. |
| final String podspecPath = podspec.path; |
| |
| final String podspecBasename = p.basename(podspecPath); |
| print('Linting $podspecBasename'); |
| |
| // Lint plugin as framework (use_frameworks!). |
| final ProcessResult frameworkResult = |
| await _runPodLint(podspecPath, libraryLint: true); |
| print(frameworkResult.stdout); |
| print(frameworkResult.stderr); |
| |
| // Lint plugin as library. |
| final ProcessResult libraryResult = |
| await _runPodLint(podspecPath, libraryLint: false); |
| print(libraryResult.stdout); |
| print(libraryResult.stderr); |
| |
| return frameworkResult.exitCode == 0 && libraryResult.exitCode == 0; |
| } |
| |
| Future<ProcessResult> _runPodLint(String podspecPath, |
| {required bool libraryLint}) async { |
| final List<String> arguments = <String>[ |
| 'lib', |
| 'lint', |
| podspecPath, |
| '--configuration=Debug', // Release targets unsupported arm64 simulators. Use Debug to only build against targeted x86_64 simulator devices. |
| '--skip-tests', |
| '--use-modular-headers', // Flutter sets use_modular_headers! in its templates. |
| if (libraryLint) '--use-libraries' |
| ]; |
| |
| print('Running "pod ${arguments.join(' ')}"'); |
| return processRunner.run('pod', arguments, |
| workingDir: packagesDir, stdoutEncoding: utf8, stderrEncoding: utf8); |
| } |
| } |