// Copyright (C) 2024 Simon Quigley // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include "archive.h" #include "utils.h" #include "launchpad.h" #include "source_package_publishing_history.h" #include #include archive::archive() : authorized_size(0), build_debug_symbols(false), description(""), displayname(""), distribution_link(""), external_dependencies(""), metadata_overrides(nlohmann::json::object()), name(""), owner_link(""), permit_obsolete_series_uploads(false), is_private(false), publish(false), publish_debug_symbols(false), publishing_method(""), relative_build_score(0), repository_format(""), require_virtualized(false), signing_key_fingerprint(""), suppress_subscription_notifications(false), owner_name(""), ppa_name(""), lp(nullptr) {} archive::~archive() {} std::optional archive::parse(const std::string& json_data) { archive a; a.parse_json(json_data); return a; } void archive::parse_json(const std::string& json_data) { if (json_data.empty()) { std::cerr << "Error: Empty JSON data for archive::parse_json." << std::endl; return; } try { auto data = nlohmann::json::parse(json_data); // Map JSON keys to member variable setters std::map> json_map = { {"authorized_size", [this](const nlohmann::json& val) { authorized_size = val.get(); }}, {"build_debug_symbols", [this](const nlohmann::json& val) { build_debug_symbols = val.get(); }}, {"description", [this](const nlohmann::json& val) { description = val.get(); }}, {"displayname", [this](const nlohmann::json& val) { displayname = val.get(); }}, {"distribution_link", [this](const nlohmann::json& val) { distribution_link = val.get(); }}, {"external_dependencies", [this](const nlohmann::json& val) { external_dependencies = val.get(); }}, {"metadata_overrides", [this](const nlohmann::json& val) { metadata_overrides = val; }}, {"name", [this](const nlohmann::json& val) { name = val.get(); }}, {"owner_link", [this](const nlohmann::json& val) { owner_link = val.get(); }}, {"permit_obsolete_series_uploads", [this](const nlohmann::json& val) { permit_obsolete_series_uploads = val.get(); }}, {"private", [this](const nlohmann::json& val) { is_private = val.get(); }}, {"publish", [this](const nlohmann::json& val) { publish = val.get(); }}, {"publish_debug_symbols", [this](const nlohmann::json& val) { publish_debug_symbols = val.get(); }}, {"publishing_method", [this](const nlohmann::json& val) { publishing_method = val.get(); }}, {"relative_build_score", [this](const nlohmann::json& val) { relative_build_score = val.get(); }}, {"repository_format", [this](const nlohmann::json& val) { repository_format = val.get(); }}, {"require_virtualized", [this](const nlohmann::json& val) { require_virtualized = val.get(); }}, {"signing_key_fingerprint", [this](const nlohmann::json& val) { signing_key_fingerprint = val.get(); }}, {"suppress_subscription_notifications", [this](const nlohmann::json& val) { suppress_subscription_notifications = val.get(); }} }; // Handle read-only fields separately std::map> readonly_map = { {"dependencies_collection_link", [this](const nlohmann::json& val) { dependencies_collection_link = val.get(); }}, {"enabled_restricted_processors_collection_link", [this](const nlohmann::json& val) { enabled_restricted_processors_collection_link = val.get(); }}, {"http_etag", [this](const nlohmann::json& val) { http_etag = val.get(); }}, {"processors_collection_link", [this](const nlohmann::json& val) { processors_collection_link = val.get(); }}, {"reference", [this](const nlohmann::json& val) { reference = val.get(); }}, {"resource_type_link", [this](const nlohmann::json& val) { resource_type_link = val.get(); }}, {"self_link", [this](const nlohmann::json& val) { self_link = val.get(); }}, {"status", [this](const nlohmann::json& val) { status = val.get(); }}, {"web_link", [this](const nlohmann::json& val) { web_link = val.get(); }} }; // Process all keys in the JSON object for (auto& [key, value] : data.items()) { try { if (json_map.find(key) != json_map.end()) { json_map[key](value); json_map.erase(key); } else if (readonly_map.find(key) != readonly_map.end()) { readonly_map[key](value); readonly_map.erase(key); } } catch (const std::exception& e) { continue; } } // Special handling for owner_name and ppa_name std::string link = owner_link; size_t pos = link.find("~"); if (pos != std::string::npos) { owner_name = link.substr(pos + 1); if (!owner_name.empty() && owner_name.back() == '/') { owner_name.pop_back(); } } ppa_name = name; } catch (const nlohmann::json::parse_error& e) { std::cerr << "JSON parse error in archive::parse_json: " << e.what() << std::endl; std::cerr << "Input JSON was: " << json_data << std::endl; } catch (const std::exception& e) { std::cerr << "Unexpected error during JSON parsing: " << e.what() << std::endl; } } std::string archive::build_archive_endpoint() const { return "~" + url_encode(owner_name) + "/" + url_encode(ppa_name); } std::generator archive::getPublishedSources(const std::string& status) const { std::map params; params["ws.op"] = "getPublishedSources"; params["status"] = status; auto response = lp->api_get(this->self_link, params); auto data = nlohmann::json::parse(response.value()); while (response.has_value() && data.contains("next_collection_link") && data["next_collection_link"] != "") { try { if (data.contains("entries") && data["entries"].is_array()) { for (auto& entry : data["entries"]) { auto s_opt = source_package_publishing_history::parse(entry.dump()); if (!s_opt) continue; s_opt->set_lp(lp); co_yield s_opt.value(); } } response = lp->api_get(data["next_collection_link"]); data = nlohmann::json::parse(response.value()); } catch (const std::exception& e) { std::cerr << "Error parsing published sources: " << e.what() << std::endl; } } } void archive::set_lp(launchpad* lp_ptr) { lp = lp_ptr; }