Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[flutter_plugin_tools] Improve license-check output #4154

Merged
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
4 changes: 4 additions & 0 deletions script/tool/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## NEXT

- Improved `license-check` output.

## 0.4.0

- Modified the output format of many commands
Expand Down
122 changes: 65 additions & 57 deletions script/tool/lib/src/license_check_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,21 +107,65 @@ class LicenseCheckCommand extends PluginCommand {

@override
Future<void> run() async {
final Iterable<File> codeFiles = (await _getAllFiles()).where((File file) =>
final Iterable<File> allFiles = await _getAllFiles();

final Iterable<File> codeFiles = allFiles.where((File file) =>
_codeFileExtensions.contains(p.extension(file.path)) &&
!_shouldIgnoreFile(file));
final Iterable<File> firstPartyLicenseFiles = (await _getAllFiles()).where(
(File file) =>
path.basename(file.basename) == 'LICENSE' && !_isThirdParty(file));
final Iterable<File> firstPartyLicenseFiles = allFiles.where((File file) =>
path.basename(file.basename) == 'LICENSE' && !_isThirdParty(file));

final bool copyrightCheckSucceeded = await _checkCodeLicenses(codeFiles);
print('\n=======================================\n');
final bool licenseCheckSucceeded =
final List<File> licenseFileFailures =
await _checkLicenseFiles(firstPartyLicenseFiles);
final Map<_LicenseFailureType, List<File>> codeFileFailures =
await _checkCodeLicenses(codeFiles);

bool passed = true;

print('\n=======================================\n');

if (licenseFileFailures.isNotEmpty) {
passed = false;
printError(
'The following LICENSE files do not follow the expected format:');
for (final File file in licenseFileFailures) {
printError(' ${file.path}');
}
printError('Please ensure that they use the exact format used in this '
'repository".\n');
}

if (codeFileFailures[_LicenseFailureType.incorrectFirstParty]!.isNotEmpty) {
passed = false;
printError('The license block for these files is missing or incorrect:');
for (final File file
in codeFileFailures[_LicenseFailureType.incorrectFirstParty]!) {
printError(' ${file.path}');
}
printError(
'If this third-party code, move it to a "third_party/" directory, '
'otherwise ensure that you are using the exact copyright and license '
'text used by all first-party files in this repository.\n');
}

if (codeFileFailures[_LicenseFailureType.unknownThirdParty]!.isNotEmpty) {
passed = false;
printError(
'No recognized license was found for the following third-party files:');
for (final File file
in codeFileFailures[_LicenseFailureType.unknownThirdParty]!) {
printError(' ${file.path}');
}
print('Please check that they have a license at the top of the file. '
'If they do, the license check needs to be updated to recognize '
'the new third-party license block.\n');
}

if (!copyrightCheckSucceeded || !licenseCheckSucceeded) {
if (!passed) {
throw ToolExit(1);
}

printSuccess('All files passed validation!');
}

// Creates the expected copyright+license block for first-party code.
Expand All @@ -135,9 +179,10 @@ class LicenseCheckCommand extends PluginCommand {
'${comment}found in the LICENSE file.$suffix\n';
}

// Checks all license blocks for [codeFiles], returning false if any of them
// fail validation.
Future<bool> _checkCodeLicenses(Iterable<File> codeFiles) async {
/// Checks all license blocks for [codeFiles], returning any that fail
/// validation.
Future<Map<_LicenseFailureType, List<File>>> _checkCodeLicenses(
Iterable<File> codeFiles) async {
final List<File> incorrectFirstPartyFiles = <File>[];
final List<File> unrecognizedThirdPartyFiles = <File>[];

Expand Down Expand Up @@ -171,46 +216,21 @@ class LicenseCheckCommand extends PluginCommand {
}
}
}
print('\n');

// Sort by path for more usable output.
final int Function(File, File) pathCompare =
(File a, File b) => a.path.compareTo(b.path);
incorrectFirstPartyFiles.sort(pathCompare);
unrecognizedThirdPartyFiles.sort(pathCompare);

if (incorrectFirstPartyFiles.isNotEmpty) {
print('The license block for these files is missing or incorrect:');
for (final File file in incorrectFirstPartyFiles) {
print(' ${file.path}');
}
print('If this third-party code, move it to a "third_party/" directory, '
'otherwise ensure that you are using the exact copyright and license '
'text used by all first-party files in this repository.\n');
}

if (unrecognizedThirdPartyFiles.isNotEmpty) {
print(
'No recognized license was found for the following third-party files:');
for (final File file in unrecognizedThirdPartyFiles) {
print(' ${file.path}');
}
print('Please check that they have a license at the top of the file. '
'If they do, the license check needs to be updated to recognize '
'the new third-party license block.\n');
}

final bool succeeded =
incorrectFirstPartyFiles.isEmpty && unrecognizedThirdPartyFiles.isEmpty;
if (succeeded) {
print('All source files passed validation!');
}
return succeeded;
return <_LicenseFailureType, List<File>>{
_LicenseFailureType.incorrectFirstParty: incorrectFirstPartyFiles,
_LicenseFailureType.unknownThirdParty: unrecognizedThirdPartyFiles,
};
}

// Checks all provide LICENSE files, returning false if any of them
// fail validation.
Future<bool> _checkLicenseFiles(Iterable<File> files) async {
/// Checks all provided LICENSE [files], returning any that fail validation.
Future<List<File>> _checkLicenseFiles(Iterable<File> files) async {
final List<File> incorrectLicenseFiles = <File>[];

for (final File file in files) {
Expand All @@ -219,22 +239,8 @@ class LicenseCheckCommand extends PluginCommand {
incorrectLicenseFiles.add(file);
}
}
print('\n');

if (incorrectLicenseFiles.isNotEmpty) {
print('The following LICENSE files do not follow the expected format:');
for (final File file in incorrectLicenseFiles) {
print(' ${file.path}');
}
print(
'Please ensure that they use the exact format used in this repository".\n');
}

final bool succeeded = incorrectLicenseFiles.isEmpty;
if (succeeded) {
print('All LICENSE files passed validation!');
}
return succeeded;
return incorrectLicenseFiles;
}

bool _shouldIgnoreFile(File file) {
Expand All @@ -255,3 +261,5 @@ class LicenseCheckCommand extends PluginCommand {
.map((FileSystemEntity file) => file as File)
.toList();
}

enum _LicenseFailureType { incorrectFirstParty, unknownThirdParty }
Loading