/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #include #include #include "katja/sbo.hpp" namespace katja { info_file::info_file(const std::string& program_name, const std::string& version, const std::string homepage, const std::string& email, const std::string& maintainer) : program_name(program_name), version(version), homepage(homepage), email(email), maintainer(maintainer) { } sbo_repository::sbo_repository(const std::filesystem::path& repository_path) { search_for_slackbuilds(this->info_paths, repository_path); } std::vector sbo_repository::get_updates(const package_database& database) { std::vector identifiers; for (const auto& [package_name, package] : database) { auto looked_up_info_path = this->info_paths.find(package_name); if (looked_up_info_path != this->info_paths.cend()) { auto slackbuild_info = read_slackbuild_info(looked_up_info_path->second); if (slackbuild_info.has_value() && slackbuild_info.value().version != package.version) { identifiers.push_back({ slackbuild_info->program_name, slackbuild_info->version, package.architecture, "SBo" }); } } } return identifiers; } bool trim_info_line(std::string& info_value) { if (boost::algorithm::ends_with(info_value, "\"")) { info_value.pop_back(); return false; } else if (boost::algorithm::ends_with(info_value, "\\")) { info_value.pop_back(); return true; } return false; } std::optional read_slackbuild_info(const std::filesystem::path& info_filepath) { std::ifstream info_stream{ info_filepath }; std::string info_line, info_variable, info_value; std::string program_name, version, homepage, email, maintainer; std::vector download, md5sum, download_x86_64, md5sum_x86_64, requires; bool continuation{ false }; while (std::getline(info_stream, info_line)) { if (info_line.empty()) { continue; } else if (!continuation) { auto equals_position = std::find(info_line.cbegin(), info_line.cend(), '='); info_variable = std::string(info_line.cbegin(), equals_position); if (equals_position == info_line.cend() || ++equals_position == info_line.cend() || *equals_position != '"') { return std::nullopt; } info_value = std::string(std::next(equals_position), info_line.cend()); } else { info_value += info_line; } continuation = trim_info_line(info_value); if (!continuation) { if (info_variable == "PRGNAM") { std::swap(program_name, info_value); } else if (info_variable == "VERSION") { std::swap(version, info_value); } else if (info_variable == "HOMEPAGE") { std::swap(homepage, info_value); } else if (info_variable == "EMAIL") { std::swap(email, info_value); } else if (info_variable == "MAINTAINER") { std::swap(maintainer, info_value); } else if (info_variable == "DOWNLOAD") { boost::split(download, info_value, boost::is_any_of(" "), boost::token_compress_on); } else if (info_variable == "MD5SUM") { boost::split(md5sum, info_value, boost::is_any_of(" "), boost::token_compress_on); } else if (info_variable == "DOWNLOAD_x86_64") { boost::split(download_x86_64, info_value, boost::is_any_of(" "), boost::token_compress_on); } else if (info_variable == "MD5SUM_x86_64") { boost::split(md5sum_x86_64, info_value, boost::is_any_of(" "), boost::token_compress_on); } else if (info_variable == "REQUIRES") { boost::split(requires, info_value, boost::is_any_of(" "), boost::token_compress_on); } } } return std::make_optional(program_name, version, homepage, email, maintainer); } void search_for_slackbuilds(std::vector& info_files, const std::filesystem::path& directory) { std::map info_paths; search_for_slackbuilds(info_paths, directory); for (const auto& [_, info_filepath] : info_paths) { auto slackbuild_info = read_slackbuild_info(info_filepath); if (slackbuild_info.has_value()) { info_files.emplace_back(std::move(slackbuild_info.value())); } } } void search_for_slackbuilds(std::map& info_files, const std::filesystem::path& directory) { for (const auto& entry : std::filesystem::directory_iterator(directory)) { std::filesystem::path entry_path = entry; std::filesystem::path info_filename = entry_path.filename(); info_filename.replace_extension(".info"); std::filesystem::path info_filepath = entry_path / info_filename; if (std::filesystem::exists(info_filepath)) { info_files.emplace(entry_path.filename(), info_filepath); } else if (std::filesystem::is_directory(entry_path)) { search_for_slackbuilds(info_files, entry_path); } } } }