Handle signature file when adding/removing/moving/checking/cleaning packages

This commit is contained in:
Martchus 2021-03-14 01:53:40 +01:00
parent 94b39f55dc
commit 45bf4fa234
5 changed files with 77 additions and 9 deletions

View File

@ -245,7 +245,14 @@ BuildActionMetaInfo::BuildActionMetaInfo()
.category = "Repo management",
.name = "Check for problems",
.type = "check-for-problems",
.flags = {},
.flags = {
BuildActionFlagMetaInfo{
.id = static_cast<BuildActionFlagType>(CheckForProblemsFlags::RequirePackageSignatures),
.name = "Require package signatures",
.desc = "Checks whether package signatures are present",
.param = "require-pkg-signatures",
},
},
.settings = {
BuildActionSettingMetaInfo{
.name = "Dependencies to ignore",

View File

@ -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

View File

@ -432,6 +432,9 @@ private:
struct LIBREPOMGR_EXPORT CheckForProblems : public InternalBuildAction {
CheckForProblems(ServiceSetup &setup, const std::shared_ptr<BuildAction> &buildAction);
void run();
private:
bool m_requirePackageSignatures = false;
};
struct LIBREPOMGR_EXPORT CleanRepository : public InternalBuildAction {

View File

@ -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);

View File

@ -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<Bu
void CheckForProblems::run()
{
// read settings
const auto flags = static_cast<CheckForProblemsFlags>(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(