From 13cccd3bc9fc5411016f0c5804d13e63ca13987f Mon Sep 17 00:00:00 2001 From: Martchus Date: Tue, 15 Mar 2022 01:10:15 +0100 Subject: [PATCH] Improve creating license info --- libpkg/algo/licenses.cpp | 35 ++++++++++++++++----- librepomgr/buildactions/buildactionmeta.cpp | 2 +- librepomgr/buildactions/makelicenseinfo.cpp | 29 +++++++++++++++++ 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/libpkg/algo/licenses.cpp b/libpkg/algo/licenses.cpp index 8ac1042..2c7cdca 100644 --- a/libpkg/algo/licenses.cpp +++ b/libpkg/algo/licenses.cpp @@ -63,6 +63,7 @@ std::string Config::addLicenseInfo(LicenseResult &result, PackageSearchResult &s { "glib2", "GLib" }, { "numix-icon-theme", "Numix icon theme" }, { "breeze-icons", "Breeze icons (from KDE)" }, + { "boost", "Boost" }, { "go", "Go" }, { "syncthing", "Syncthing" }, { "syncthingtray", "Syncthing Tray" }, @@ -79,6 +80,9 @@ std::string Config::addLicenseInfo(LicenseResult &result, PackageSearchResult &s } else if (startsWith(packageID, "qt5-")) { packageID = "Qt 5"; regularPackageName = "qt5-base"; + } else if (startsWith(packageID, "qt6-")) { + packageID = "Qt 6"; + regularPackageName = "qt6-base"; } // skip package if custom license has already been added @@ -89,9 +93,12 @@ std::string Config::addLicenseInfo(LicenseResult &result, PackageSearchResult &s // check whether the package has a standard license and/or a custom license bool hasCustomLicense = package->licenses.empty(); - if (packageID == "Qt 5") { + if (packageID == "Qt 5" || packageID == "Qt 6") { // consider Qt's licenses custom as it has special variants of the standard licenses FDL, GPL and LGPL hasCustomLicense = true; + } else if (packageID == "GCC") { + // override GCC license, it is GPL3 and not GPL2 and above; besides, we don't care about the documentation here + result.commonLicenses["GPL3"].relevantPackages.emplace(packageID); } else { // read the package's license field (see https://wiki.archlinux.org/index.php/PKGBUILD#license) for (const auto &license : package->licenses) { @@ -101,13 +108,20 @@ std::string Config::addLicenseInfo(LicenseResult &result, PackageSearchResult &s hasCustomLicense = true; continue; } - // map Arch Linux generic way to say e.g. "GPL2 and above" to a concrete license e.g. "GPL2" auto concreteLicense = license; if (license == "GPL") { - concreteLicense = "GPL2"; - } else if (license == "LGPL" || license == "LGPL2") { - concreteLicense = "LGPL2.1"; + concreteLicense = "GPL2 or any later version"; + } else if (license == "GPL2") { + concreteLicense = "GPL2 only"; + } else if (license == "GPL3") { + concreteLicense = "GPL3 or any later version"; + } else if (license == "LGPL") { + concreteLicense = "LGPL2 or any later version"; + } else if (license == "LGPL2") { + concreteLicense = "LGPL2 only"; + } else if (license == "LGPL3") { + concreteLicense = "LGPL3 or any later version"; } else if (license == "FDL") { concreteLicense = "FDL1.2"; } else if (license == "AGPL") { @@ -230,7 +244,7 @@ LicenseResult Config::computeLicenseInfo(const std::vector &dependencyDe return result; } const auto path = db->localPkgDir % '/' + licensesPackage->packageInfo->fileName; - decltype(extractFiles(path, &Package::isLicense)) licensesDirs; + auto licensesDirs = FileMap(); try { licensesDirs = extractFiles(path, &Package::isLicense); if (licensesDirs.empty()) { @@ -253,7 +267,14 @@ LicenseResult Config::computeLicenseInfo(const std::vector &dependencyDe for (auto &commonLicense : result.commonLicenses) { const auto &licenseName = commonLicense.first; auto &license = commonLicense.second; - const auto dir = licensesDirs.find("usr/share/licenses/common/" + licenseName); + auto dir = licensesDirs.find("usr/share/licenses/common/" + licenseName); + if (dir == licensesDirs.end() || dir->second.empty()) { + if (const auto whiteSpace = licenseName.find(' '); whiteSpace != std::string::npos) { + const auto plainLicense = std::string_view(licenseName.data(), whiteSpace); + const auto licenseSuffix = std::string_view(plainLicense == "LGPL2" ? ".1" : ""); + dir = licensesDirs.find(argsToString("usr/share/licenses/common/", plainLicense, licenseSuffix)); + } + } if (dir == licensesDirs.end() || dir->second.empty()) { result.success = false; result.notes.emplace_back("Unable to find license dir for common license " + licenseName); diff --git a/librepomgr/buildactions/buildactionmeta.cpp b/librepomgr/buildactions/buildactionmeta.cpp index a3d007a..1f4a1cd 100644 --- a/librepomgr/buildactions/buildactionmeta.cpp +++ b/librepomgr/buildactions/buildactionmeta.cpp @@ -255,7 +255,7 @@ BuildActionMetaInfo::BuildActionMetaInfo() .type = "make-license-info", .flags = {}, .settings = {}, - .directory = false, + .directory = true, .sourceDb = false, .destinationDb = false, .packageNames = true, diff --git a/librepomgr/buildactions/makelicenseinfo.cpp b/librepomgr/buildactions/makelicenseinfo.cpp index 01222a3..fded904 100644 --- a/librepomgr/buildactions/makelicenseinfo.cpp +++ b/librepomgr/buildactions/makelicenseinfo.cpp @@ -2,6 +2,11 @@ #include "../serversetup.h" +#include +#include + +using namespace CppUtilities; + namespace LibRepoMgr { MakeLicenseInfo::MakeLicenseInfo(ServiceSetup &setup, const std::shared_ptr &buildAction) @@ -11,6 +16,16 @@ MakeLicenseInfo::MakeLicenseInfo(ServiceSetup &setup, const std::shared_ptrdirectory.empty()) { + reportError("Unable to create working directory: no directory name specified"); + return; + } + auto setupReadLock = m_setup.lockToRead(); + auto outputDir = m_setup.building.workingDirectory % "/license-info/" + m_buildAction->directory; + setupReadLock.unlock(); + + // validate params and acquire read lock auto configReadLock = init(BuildActionAccess::ReadConfig, RequiredDatabases::None, RequiredParameters::Packages); if (std::holds_alternative(configReadLock)) { return; @@ -18,8 +33,22 @@ void MakeLicenseInfo::run() auto result = m_setup.config.computeLicenseInfo(m_buildAction->packageNames); std::get>(configReadLock).unlock(); + auto wroteOutputFile = false; + auto outputFilePath = outputDir % '/' % m_buildAction->id + "-summary.md"; + try { + std::filesystem::create_directories(outputDir); + writeFile(outputFilePath, result.licenseSummary); + result.licenseSummary = std::move(outputFilePath); + wroteOutputFile = true; + } catch (const std::exception &e) { + result.notes.emplace_back("Unable to write output file \"" % outputFilePath % "\": " + e.what()); + result.success = false; + } const auto buildActionWriteLock = m_setup.building.lockToWrite(); + if (wroteOutputFile) { + m_buildAction->artefacts.emplace_back(result.licenseSummary); + } m_buildAction->resultData = std::move(result); reportResult(result.success ? BuildActionResult::Success : BuildActionResult::Failure); }