From 45bf4fa23448a31a48a2a976de1b3818a7579856 Mon Sep 17 00:00:00 2001 From: Martchus Date: Sun, 14 Mar 2021 01:53:40 +0100 Subject: [PATCH] Handle signature file when adding/removing/moving/checking/cleaning packages --- librepomgr/buildactions/buildactionmeta.cpp | 9 +++- librepomgr/buildactions/buildactionmeta.h | 5 ++ librepomgr/buildactions/buildactionprivate.h | 3 ++ librepomgr/buildactions/conductbuild.cpp | 16 +++++- librepomgr/buildactions/repomanagement.cpp | 53 +++++++++++++++++--- 5 files changed, 77 insertions(+), 9 deletions(-) diff --git a/librepomgr/buildactions/buildactionmeta.cpp b/librepomgr/buildactions/buildactionmeta.cpp index 6917721..bfc3fdc 100644 --- a/librepomgr/buildactions/buildactionmeta.cpp +++ b/librepomgr/buildactions/buildactionmeta.cpp @@ -245,7 +245,14 @@ BuildActionMetaInfo::BuildActionMetaInfo() .category = "Repo management", .name = "Check for problems", .type = "check-for-problems", - .flags = {}, + .flags = { + BuildActionFlagMetaInfo{ + .id = static_cast(CheckForProblemsFlags::RequirePackageSignatures), + .name = "Require package signatures", + .desc = "Checks whether package signatures are present", + .param = "require-pkg-signatures", + }, + }, .settings = { BuildActionSettingMetaInfo{ .name = "Dependencies to ignore", diff --git a/librepomgr/buildactions/buildactionmeta.h b/librepomgr/buildactions/buildactionmeta.h index edb1bdc..b305c7a 100644 --- a/librepomgr/buildactions/buildactionmeta.h +++ b/librepomgr/buildactions/buildactionmeta.h @@ -74,6 +74,10 @@ enum class ConductBuildFlags : BuildActionFlagType { UpdateChecksums = (1 << 2), AutoStaging = (1 << 3), }; +enum class CheckForProblemsFlags : BuildActionFlagType { + None, + RequirePackageSignatures = (1 << 0), +}; enum class CleanRepositoryFlags : BuildActionFlagType { None, DryRun = (1 << 0), @@ -176,5 +180,6 @@ CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(LibRepoMgr, LibRepoMgr::ReloadLibraryDependen CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(LibRepoMgr, LibRepoMgr::PrepareBuildFlags) CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(LibRepoMgr, LibRepoMgr::ConductBuildFlags) CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(LibRepoMgr, LibRepoMgr::CleanRepositoryFlags) +CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(LibRepoMgr, LibRepoMgr::CheckForProblemsFlags) #endif // LIBREPOMGR_BUILD_ACTION_META_H diff --git a/librepomgr/buildactions/buildactionprivate.h b/librepomgr/buildactions/buildactionprivate.h index 9a116cd..5cd3f3b 100644 --- a/librepomgr/buildactions/buildactionprivate.h +++ b/librepomgr/buildactions/buildactionprivate.h @@ -432,6 +432,9 @@ private: struct LIBREPOMGR_EXPORT CheckForProblems : public InternalBuildAction { CheckForProblems(ServiceSetup &setup, const std::shared_ptr &buildAction); void run(); + +private: + bool m_requirePackageSignatures = false; }; struct LIBREPOMGR_EXPORT CleanRepository : public InternalBuildAction { diff --git a/librepomgr/buildactions/conductbuild.cpp b/librepomgr/buildactions/conductbuild.cpp index 91d3b82..19e2a0a 100644 --- a/librepomgr/buildactions/conductbuild.cpp +++ b/librepomgr/buildactions/conductbuild.cpp @@ -1092,19 +1092,33 @@ void ConductBuild::addPackageToRepo( std::filesystem::create_directories(sourceRepoPath); std::filesystem::copy(sourcePackagePath, sourceRepoPath / sourcePackageName, std::filesystem::copy_options::update_existing); for (const auto &binaryPackage : binaryPackages) { + const auto signaturePath = std::filesystem::path(argsToString(binaryPackage.path, ".sig")); if (!binaryPackage.isAny) { std::filesystem::copy(binaryPackage.path, repoPath % '/' + *binaryPackage.fileName, std::filesystem::copy_options::update_existing); + if (std::filesystem::exists(signaturePath)) { + std::filesystem::copy( + signaturePath, repoPath % '/' % *binaryPackage.fileName + ".sig", std::filesystem::copy_options::update_existing); + } continue; } if (anyRepoPath.empty()) { std::filesystem::create_directories(anyRepoPath = repoPath + "/../any"); } std::filesystem::copy(binaryPackage.path, anyRepoPath / *binaryPackage.fileName, std::filesystem::copy_options::update_existing); - const std::filesystem::path symlink = repoPath % '/' + *binaryPackage.fileName; + const auto symlink = std::filesystem::path(repoPath % '/' + *binaryPackage.fileName); if (std::filesystem::exists(symlink) && !std::filesystem::is_symlink(symlink)) { std::filesystem::remove(symlink); } std::filesystem::create_symlink("../any/" + *binaryPackage.fileName, symlink); + if (std::filesystem::exists(signaturePath)) { + std::filesystem::copy( + signaturePath, argsToString(anyRepoPath, '/', *binaryPackage.fileName, ".sig"), std::filesystem::copy_options::update_existing); + const auto symlink = std::filesystem::path(argsToString(repoPath, '/', *binaryPackage.fileName, ".sig")); + if (std::filesystem::exists(symlink) && !std::filesystem::is_symlink(symlink)) { + std::filesystem::remove(symlink); + } + std::filesystem::create_symlink("../any/" % *binaryPackage.fileName + ".sig", symlink); + } } } catch (const std::filesystem::filesystem_error &e) { auto writeLock = lockToWrite(readLock); diff --git a/librepomgr/buildactions/repomanagement.cpp b/librepomgr/buildactions/repomanagement.cpp index 5f91f6e..0d8ee4f 100644 --- a/librepomgr/buildactions/repomanagement.cpp +++ b/librepomgr/buildactions/repomanagement.cpp @@ -192,20 +192,30 @@ void RemovePackages::handleRepoRemoveResult(boost::process::child &&child, Proce void RemovePackages::movePackagesToArchive() { m_buildAction->log()(Phrases::InfoMessage, "Moving packages to archive directory"); - std::filesystem::path archivePath; + std::filesystem::path archivePath, destPath, signatureFile; auto processedPackageIterator = m_result.processedPackages.begin(); for (const auto &[packageName, packageLocation, ok] : m_packageLocations) { try { archivePath = packageLocation.pathWithinRepo.parent_path() / "archive"; + destPath = archivePath / packageLocation.pathWithinRepo.filename(); + signatureFile = argsToString(packageLocation.pathWithinRepo, ".sig"); std::filesystem::create_directory(archivePath); - std::filesystem::rename(packageLocation.pathWithinRepo, archivePath / packageLocation.pathWithinRepo.filename()); + std::filesystem::rename(packageLocation.pathWithinRepo, destPath); + if (std::filesystem::exists(signatureFile)) { + std::filesystem::rename(signatureFile, argsToString(destPath, ".sig")); + } if (packageLocation.storageLocation.empty()) { continue; } // FIXME: The file at the storage location *might* still be used elsewhere. Better leave that to a repo cleanup task (to be implemented later). archivePath = packageLocation.storageLocation.parent_path() / "archive"; + destPath = archivePath / packageLocation.storageLocation.filename(); + signatureFile = argsToString(packageLocation.storageLocation, ".sig"); std::filesystem::create_directory(archivePath); - std::filesystem::rename(packageLocation.storageLocation, archivePath / packageLocation.storageLocation.filename()); + std::filesystem::rename(packageLocation.storageLocation, destPath); + if (std::filesystem::exists(signatureFile)) { + std::filesystem::rename(signatureFile, argsToString(destPath, ".sig")); + } ++processedPackageIterator; } catch (const std::filesystem::filesystem_error &e) { processedPackageIterator = m_result.processedPackages.erase(processedPackageIterator); @@ -236,8 +246,13 @@ void MovePackages::run() m_result.processedPackages.reserve(m_packageLocations.size()); for (auto &[packageName, packageLocation, ok] : m_packageLocations) { try { + const auto destPath = m_destinationRepoDirectory / packageLocation.pathWithinRepo.filename(); + const auto signatureFile = std::filesystem::path(argsToString(packageLocation.pathWithinRepo, ".sig")); if (packageLocation.storageLocation.empty()) { - std::filesystem::copy_file(packageLocation.pathWithinRepo, m_destinationRepoDirectory / packageLocation.pathWithinRepo.filename()); + std::filesystem::copy_file(packageLocation.pathWithinRepo, destPath); + if (std::filesystem::exists(signatureFile)) { + std::filesystem::copy_file(signatureFile, argsToString(destPath, ".sig")); + } } else { const auto symlinkTarget = std::filesystem::read_symlink(packageLocation.pathWithinRepo); if (symlinkTarget.is_absolute()) { @@ -248,11 +263,17 @@ void MovePackages::run() continue; } const auto newStorageLocation = m_destinationRepoDirectory / symlinkTarget; + const auto storageSignatureFile = std::filesystem::path(argsToString(packageLocation.storageLocation, ".sig")); std::filesystem::create_directory( newStorageLocation.parent_path()); // ensure the parent, e.g. the "any" directory exists; assume further parents already exist - std::filesystem::copy(packageLocation.pathWithinRepo, m_destinationRepoDirectory / packageLocation.pathWithinRepo.filename(), - std::filesystem::copy_options::copy_symlinks); + std::filesystem::copy(packageLocation.pathWithinRepo, destPath, std::filesystem::copy_options::copy_symlinks); std::filesystem::copy_file(packageLocation.storageLocation, newStorageLocation); + if (std::filesystem::exists(signatureFile)) { + std::filesystem::copy(signatureFile, argsToString(destPath, ".sig"), std::filesystem::copy_options::copy_symlinks); + } + if (std::filesystem::exists(storageSignatureFile)) { + std::filesystem::copy_file(storageSignatureFile, argsToString(newStorageLocation, ".sig")); + } } } catch (const std::filesystem::filesystem_error &e) { ok = false; @@ -387,6 +408,8 @@ CheckForProblems::CheckForProblems(ServiceSetup &setup, const std::shared_ptr(m_buildAction->flags); + m_requirePackageSignatures = flags & CheckForProblemsFlags::RequirePackageSignatures; auto &metaInfo = m_setup.building.metaInfo; auto metaInfoLock = metaInfo.lockToRead(); const auto &typeInfo = metaInfo.typeInfoForId(BuildActionType::CheckForProblems); @@ -436,6 +459,13 @@ void CheckForProblems::run() problems.emplace_back( RepositoryProblem{ .desc = "binary package \"" % pkg->packageInfo->fileName + "\" not present", .pkg = pkgName }); } + if (m_requirePackageSignatures) { + const auto signatureLocation = db->locatePackage(pkg->packageInfo->fileName + ".sig"); + if (!signatureLocation.exists) { + problems.emplace_back(RepositoryProblem{ + .desc = "signature file for package \"" % pkg->packageInfo->fileName + "\" not present", .pkg = pkgName }); + } + } } } catch (const std::filesystem::filesystem_error &e) { problems.emplace_back(RepositoryProblem{ .desc = argsToString("unable to check presence of files: ", e.what()) }); @@ -739,7 +769,11 @@ void CleanRepository::run() for (auto &toDelete : dirInfo.toDelete) { try { if (!m_dryRun) { + const auto signatureFile = std::filesystem::path(argsToString(toDelete, ".sig")); std::filesystem::remove(toDelete); + if (std::filesystem::exists(signatureFile)) { + std::filesystem::remove(signatureFile); + } } ++processesItems; m_messages.notes.emplace_back("Deleted " + toDelete.string()); @@ -760,7 +794,12 @@ void CleanRepository::run() for (const auto &[path, referencedPath] : dirInfo.toArchive) { try { if (!m_dryRun) { - std::filesystem::rename(path, archiveDir / path.filename()); + const auto destPath = archiveDir / path.filename(); + const auto signatureFile = std::filesystem::path(argsToString(path, ".sig")); + std::filesystem::rename(path, destPath); + if (std::filesystem::exists(signatureFile)) { + std::filesystem::rename(signatureFile, argsToString(destPath, ".sig")); + } } ++processesItems; m_messages.notes.emplace_back(