From e5de0f5b308fb4f5357633279816f211c799e8bb Mon Sep 17 00:00:00 2001 From: Kai Koehne <kai.koehne@qt.io> Date: Fri, 4 Aug 2017 08:54:31 +0200 Subject: [PATCH] qtattributionsscanner: Allow to use it for one single file This allows a saner use with qbs, where we can and should actually handle the dependencies correctly. In addition, this patch adds an optional '--basedir' argument that is needed to correctly root relative paths that are printed in the documentation. Change-Id: I0abf769ad5c0a3ac15b6907f83b77d369eb78d1f GPush-Base: 5c8d5742dc7b5e00a6aed447e8f288680b58e225 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io> --- src/qtattributionsscanner/main.cpp | 49 ++++++++++++++----- src/qtattributionsscanner/scanner.cpp | 2 +- src/qtattributionsscanner/scanner.h | 1 + .../testdata/good/minimal/expected.error | 0 .../testdata/good/minimal/expected.json | 21 ++++++++ .../tst_qtattributionsscanner.cpp | 44 ++++++++++++----- 6 files changed, 92 insertions(+), 25 deletions(-) create mode 100644 tests/auto/qtattributionsscanner/testdata/good/minimal/expected.error create mode 100644 tests/auto/qtattributionsscanner/testdata/good/minimal/expected.json diff --git a/src/qtattributionsscanner/main.cpp b/src/qtattributionsscanner/main.cpp index cd9bc1fed..700bf8814 100644 --- a/src/qtattributionsscanner/main.cpp +++ b/src/qtattributionsscanner/main.cpp @@ -44,12 +44,13 @@ int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); a.setApplicationName(QStringLiteral("Qt Attributions Scanner")); - a.setApplicationVersion(QStringLiteral("1.0")); + a.setApplicationVersion(QStringLiteral("1.1")); QCommandLineParser parser; - parser.setApplicationDescription(tr("Searches and processes qt_attribution.json files in Qt sources.")); - parser.addPositionalArgument(QStringLiteral("directory"), - tr("The directory to scan recursively.")); + parser.setApplicationDescription(tr("Processes qt_attribution.json files in Qt sources.")); + parser.addPositionalArgument(QStringLiteral("path"), + tr("Path to a qt_attribution.json file, " + "or a directory to be scannned recursively.")); parser.addHelpOption(); parser.addVersionOption(); @@ -60,6 +61,10 @@ int main(int argc, char *argv[]) QCommandLineOption filterOption(QStringLiteral("filter"), tr("Filter packages according to <filter> (e.g. QDocModule=qtcore)"), QStringLiteral("expression")); + QCommandLineOption baseDirOption(QStringLiteral("basedir"), + tr("Paths in documentation are made relative to this " + "directory."), + QStringLiteral("directory")); QCommandLineOption outputOption({ QStringLiteral("o"), QStringLiteral("output") }, tr("Write generated data to <file>."), QStringLiteral("file")); @@ -70,6 +75,7 @@ int main(int argc, char *argv[]) parser.addOption(generatorOption); parser.addOption(filterOption); + parser.addOption(baseDirOption); parser.addOption(outputOption); parser.addOption(verboseOption); parser.addOption(silentOption); @@ -90,13 +96,22 @@ int main(int argc, char *argv[]) if (parser.positionalArguments().size() != 1) parser.showHelp(2); - const QString directory = parser.positionalArguments().last(); - - if (logLevel == VerboseLog) - std::cerr << qPrintable(tr("Recursively scanning %1 for qt_attribution.json files...").arg( - QDir::toNativeSeparators(directory))) << std::endl; - - QVector<Package> packages = Scanner::scanDirectory(directory, logLevel); + const QString path = parser.positionalArguments().last(); + + QVector<Package> packages; + const QFileInfo pathInfo(path); + if (pathInfo.isDir()) { + if (logLevel == VerboseLog) + std::cerr << qPrintable(tr("Recursively scanning %1 for qt_attribution.json files...").arg( + QDir::toNativeSeparators(path))) << std::endl; + packages = Scanner::scanDirectory(path, logLevel); + } else if (pathInfo.isFile()) { + packages = Scanner::readFile(path, logLevel); + } else { + std::cerr << qPrintable(tr("%1 is not a valid file or directory.").arg( + QDir::toNativeSeparators(path))) << std::endl << std::endl; + parser.showHelp(7); + } if (parser.isSet(filterOption)) { PackageFilter filter(parser.value(filterOption)); @@ -124,8 +139,16 @@ int main(int argc, char *argv[]) QString generator = parser.value(generatorOption); if (generator == QLatin1String("qdoc")) { - // include top level module name in printed paths - QString baseDirectory = QDir(directory).absoluteFilePath(QStringLiteral("..")); + QString baseDirectory = parser.value(baseDirOption); + if (baseDirectory.isEmpty()) { + if (pathInfo.isDir()) { + // include top level module name in printed paths + baseDirectory = pathInfo.dir().absoluteFilePath(QStringLiteral("..")); + } else { + baseDirectory = pathInfo.absoluteDir().absoluteFilePath(QStringLiteral("..")); + } + } + QDocGenerator::generate(out, packages, baseDirectory, logLevel); } else if (generator == QLatin1String("json")) { JsonGenerator::generate(out, packages, logLevel); diff --git a/src/qtattributionsscanner/scanner.cpp b/src/qtattributionsscanner/scanner.cpp index 488417e89..d7d958138 100644 --- a/src/qtattributionsscanner/scanner.cpp +++ b/src/qtattributionsscanner/scanner.cpp @@ -140,7 +140,7 @@ static Package readPackage(const QJsonObject &object, const QString &filePath, L return p; } -static QVector<Package> readFile(const QString &filePath, LogLevel logLevel) +QVector<Package> readFile(const QString &filePath, LogLevel logLevel) { if (logLevel == VerboseLog) { std::cerr << qPrintable(tr("Reading file %1...").arg( diff --git a/src/qtattributionsscanner/scanner.h b/src/qtattributionsscanner/scanner.h index 5d93cb8ee..f3ae9f0ea 100644 --- a/src/qtattributionsscanner/scanner.h +++ b/src/qtattributionsscanner/scanner.h @@ -37,6 +37,7 @@ namespace Scanner { +QVector<Package> readFile(const QString &filePath, LogLevel logLevel); QVector<Package> scanDirectory(const QString &directory, LogLevel logLevel); } diff --git a/tests/auto/qtattributionsscanner/testdata/good/minimal/expected.error b/tests/auto/qtattributionsscanner/testdata/good/minimal/expected.error new file mode 100644 index 000000000..e69de29bb diff --git a/tests/auto/qtattributionsscanner/testdata/good/minimal/expected.json b/tests/auto/qtattributionsscanner/testdata/good/minimal/expected.json new file mode 100644 index 000000000..6a75269c0 --- /dev/null +++ b/tests/auto/qtattributionsscanner/testdata/good/minimal/expected.json @@ -0,0 +1,21 @@ +[ + { + "Copyright": "Copyright", + "Description": "", + "Homepage": "", + "Id": "minimal", + "License": "License", + "LicenseFile": "", + "LicenseId": "", + "Name": "Minimal", + "Path": "%{PWD}", + "Files": "", + "QDocModule": "qtest", + "QtParts": [ + "libs" + ], + "QtUsage": "Usage", + "Version": "", + "DownloadLocation": "" + } +] diff --git a/tests/auto/qtattributionsscanner/tst_qtattributionsscanner.cpp b/tests/auto/qtattributionsscanner/tst_qtattributionsscanner.cpp index c3e8bb9b6..7740fde9b 100644 --- a/tests/auto/qtattributionsscanner/tst_qtattributionsscanner.cpp +++ b/tests/auto/qtattributionsscanner/tst_qtattributionsscanner.cpp @@ -47,6 +47,8 @@ private slots: void test(); private: + void readExpectedFile(const QString &baseDir, const QString &fileName, QByteArray *content); + QString m_cmd; QString m_basePath; }; @@ -62,25 +64,45 @@ tst_qtattributionsscanner::tst_qtattributionsscanner() void tst_qtattributionsscanner::test_data() { - QTest::addColumn<QString>("directory"); - QTest::newRow("good") << QStringLiteral("good"); - QTest::newRow("warnings (incomplete)") << QStringLiteral("warnings/incomplete"); - QTest::newRow("warnings (unknown attribute)") << QStringLiteral("warnings/unknown"); + QTest::addColumn<QString>("input"); + QTest::addColumn<QString>("stdout_file"); + QTest::addColumn<QString>("stderr_file"); + + QTest::newRow("good") + << QStringLiteral("good") + << QStringLiteral("good/expected.json") + << QStringLiteral("good/expected.error"); + QTest::newRow("warnings (incomplete)") + << QStringLiteral("warnings/incomplete") + << QStringLiteral("warnings/incomplete/expected.json") + << QStringLiteral("warnings/incomplete/expected.error"); + QTest::newRow("warnings (unknown attribute)") + << QStringLiteral("warnings/unknown") + << QStringLiteral("warnings/unknown/expected.json") + << QStringLiteral("warnings/unknown/expected.error"); + QTest::newRow("singlefile") + << QStringLiteral("good/minimal/qt_attribution.json") + << QStringLiteral("good/minimal/expected.json") + << QStringLiteral("good/minimal/expected.error"); } -static void readExpectedFile(const QString &dir, const QString &fileName, QByteArray *content) +void tst_qtattributionsscanner::readExpectedFile(const QString &baseDir, const QString &fileName, QByteArray *content) { - QFile file(QDir(dir).absoluteFilePath(fileName)); + QFile file(QDir(m_basePath).absoluteFilePath(fileName)); QVERIFY2(file.open(QIODevice::ReadOnly | QIODevice::Text), "Could not open " + file.fileName().toLocal8Bit()); *content = file.readAll(); - content->replace("%{PWD}", dir.toUtf8()); + content->replace("%{PWD}", baseDir.toUtf8()); } void tst_qtattributionsscanner::test() { - QFETCH(QString, directory); + QFETCH(QString, input); + QFETCH(QString, stdout_file); + QFETCH(QString, stderr_file); - QString dir = QDir(m_basePath).absoluteFilePath(directory); + QString dir = QDir(m_basePath).absoluteFilePath(input); + if (QFileInfo(dir).isFile()) + dir = QFileInfo(dir).absolutePath(); QProcess proc; QString command = m_cmd + " " + dir + " --output-format json"; @@ -100,7 +122,7 @@ void tst_qtattributionsscanner::test() stdErr.replace(QDir::separator(), "/"); QByteArray expectedErrorOutput; - readExpectedFile(dir, "expected.error", &expectedErrorOutput); + readExpectedFile(dir, stderr_file, &expectedErrorOutput); QCOMPARE(stdErr, expectedErrorOutput); } @@ -113,7 +135,7 @@ void tst_qtattributionsscanner::test() QVERIFY2(!actualJson.isNull(), "Invalid output: " + jsonError.errorString().toLatin1()); QByteArray expectedOutput; - readExpectedFile(dir, "expected.json", &expectedOutput); + readExpectedFile(dir, stdout_file, &expectedOutput); QJsonDocument expectedJson = QJsonDocument::fromJson(expectedOutput); if (!QTest::qCompare(actualJson, expectedJson, "actualJson", "expectedJson", __FILE__, __LINE__)) { -- GitLab