File indexing completed on 2024-06-16 05:18:03
0001 /* 0002 * SPDX-FileCopyrightText: 2019 Andreas Cord-Landwehr <cordlandwehr@kde.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "directoryparser.h" 0008 #include <QCommandLineParser> 0009 #include <QCoreApplication> 0010 #include <QDebug> 0011 #include <iostream> 0012 0013 int main(int argc, char *argv[]) 0014 { 0015 const std::string hightlightOut {"\033[1;34m"}; 0016 const std::string defaultOut {"\033[0m"}; 0017 0018 QCoreApplication app(argc, argv); 0019 0020 QCommandLineParser parser; 0021 parser.setApplicationDescription("Digs into licenses and replaces them with SPDX identifiers"); 0022 parser.addHelpOption(); 0023 parser.addVersionOption(); 0024 parser.addPositionalArgument("directory", QCoreApplication::translate("main", "Source file to copy.")); 0025 0026 QCommandLineOption dryOption(QStringList() << "dry", "only show detected licenses, do not change any file"); 0027 parser.addOption(dryOption); 0028 0029 QCommandLineOption skipParserOption(QStringList() << "skipparser", "use skip parser variant (slower by factor ~5 currently, but maches more)"); 0030 parser.addOption(skipParserOption); 0031 0032 QCommandLineOption forceOption(QStringList() << "f" 0033 << "force", 0034 "convert stated directory right away, do not ask"); 0035 parser.addOption(forceOption); 0036 0037 QCommandLineOption licenseConvertOption(QStringList() << "l" 0038 << "licenses", 0039 "convert license statements to SPDX-License-Identifier, but nothing else"); 0040 parser.addOption(licenseConvertOption); 0041 0042 QCommandLineOption copyrightConvertOption(QStringList() << "c" 0043 << "copyright", 0044 "convert copyright statements to SPDX-FileCopyrightText, but nothing else"); 0045 parser.addOption(copyrightConvertOption); 0046 0047 QCommandLineOption prettyHeaderOption(QStringList() << "p" 0048 << "prettyheader", 0049 "perform pretty-print conversion on copyright comment header"); 0050 parser.addOption(prettyHeaderOption); 0051 0052 QCommandLineOption ignorePatternOption(QStringList() << "i" 0053 << "ignore", 0054 "Ignore file path matching the pattern", 0055 "ignorePattern", 0056 ""); 0057 parser.addOption(ignorePatternOption); 0058 0059 parser.process(app); 0060 0061 const QStringList args = parser.positionalArguments(); 0062 if (args.count() == 0) { 0063 qCritical() << "Required license digging directory is missing"; 0064 return 1; 0065 } 0066 const QString directory = args.at(0); 0067 const QString ignorePattern = parser.value(ignorePatternOption); 0068 0069 qInfo() << "Digging recursively all files in directory:" << directory; 0070 DirectoryParser licenseParser; 0071 if (parser.isSet(skipParserOption)) { 0072 licenseParser.setLicenseHeaderParser(DirectoryParser::LicenseParser::SKIP_PARSER); 0073 } 0074 0075 // print overview if no parameter is set 0076 if (!(parser.isSet(licenseConvertOption) || parser.isSet(copyrightConvertOption) || parser.isSet(forceOption))) { 0077 std::cout << hightlightOut << "==============================" << std::endl << "= LICENSE DETECTION OVERVIEW =" << std::endl << "==============================" << defaultOut << std::endl; 0078 const auto results = licenseParser.parseAll(directory, false, ignorePattern); 0079 int undetectedLicenses = 0; 0080 int detectedLicenses = 0; 0081 for (auto iter = results.constBegin(); iter != results.constEnd(); iter++) { 0082 if (iter.value() == LicenseRegistry::UnknownLicense) { 0083 ++undetectedLicenses; 0084 } else { 0085 ++detectedLicenses; 0086 } 0087 qInfo() << iter.key() << " --> " << iter.value(); 0088 } 0089 qInfo().nospace() << "\n" 0090 << "Undetected files: " << undetectedLicenses << " (total: " << (undetectedLicenses + detectedLicenses) << ")"; 0091 } 0092 0093 bool userWantsConversion {false}; 0094 if (!(parser.isSet(dryOption) || parser.isSet(licenseConvertOption) || parser.isSet(copyrightConvertOption) || parser.isSet(forceOption))) { 0095 std::string convertAnswer {""}; 0096 std::cout << std::endl; 0097 while (convertAnswer != "n" && convertAnswer != "y") { 0098 std::cout << "Perform file conversions? [y/n] "; 0099 std::cin >> convertAnswer; 0100 } 0101 if (convertAnswer == "y") { 0102 userWantsConversion = true; 0103 } 0104 if (convertAnswer == "n") { 0105 std::cout << "Goodbye." << std::endl; 0106 return 0; 0107 } 0108 } 0109 0110 // actual conversion steps 0111 const bool convertLicense = userWantsConversion || parser.isSet(licenseConvertOption) || parser.isSet(forceOption); 0112 0113 DirectoryParser::ConvertOptions options = DirectoryParser::ConvertOption::NONE; 0114 if (userWantsConversion || parser.isSet(copyrightConvertOption) || parser.isSet(forceOption)) { 0115 options |= DirectoryParser::ConvertOption::COPYRIGHT_TEXT; 0116 } 0117 if (parser.isSet(prettyHeaderOption)) { 0118 options |= DirectoryParser::ConvertOption::PRETTY; 0119 } 0120 0121 if (convertLicense) { 0122 std::cout << hightlightOut << "Convert license statements: starting..." << defaultOut << std::endl; 0123 licenseParser.parseAll(directory, true, ignorePattern); 0124 std::cout << hightlightOut << "Convert license statements: DONE." << defaultOut << std::endl; 0125 } 0126 0127 if (options & DirectoryParser::ConvertOption::COPYRIGHT_TEXT || options & DirectoryParser::ConvertOption::PRETTY) { 0128 std::cout << hightlightOut << "Convert copyright statements: starting..." << defaultOut << std::endl; 0129 licenseParser.convertCopyright(directory, options, ignorePattern); 0130 std::cout << hightlightOut << "Convert copyright statements: DONE." << defaultOut << std::endl; 0131 } 0132 }