// 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 "archive_permission.h" #include "binary_package_publishing_history.h" #include "archive_dependency.h" #include "build.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); 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(); }} }; 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(); }} }; 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 (...) { continue; } } std::cout << "!!!!!! " << self_link << std::endl; 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 (...) { // ignore parse errors } } std::string archive::build_archive_endpoint() const { return "~" + url_encode(owner_name) + "/" + url_encode(ppa_name); } void archive::set_lp(launchpad* lp_ptr) { lp = lp_ptr; } std::generator archive::getAllPermissions() const { std::map params = {{"ws.op", "getAllPermissions"}}; auto response = lp->api_get(self_link, params); if(!response) co_return; auto data = nlohmann::json::parse(response.value()); while (true) { if (data.contains("entries") && data["entries"].is_array()) { for (auto& entry : data["entries"]) { auto s_opt = archive_permission::parse(entry.dump()); if (!s_opt) continue; s_opt->set_lp(lp); co_yield s_opt.value(); } } if (!data.contains("next_collection_link") || data["next_collection_link"].is_null() || data["next_collection_link"] == "") break; response = lp->api_get(data["next_collection_link"].get()); if(!response) break; data = nlohmann::json::parse(response.value()); } } std::generator archive::getPublishedSources( const std::string component_name, const std::string created_since_date, std::optional ds, const bool exact_match, const bool order_by_date, const std::string pocket, const std::string source_name, const std::string status, const std::string version ) const { std::map params = { {"exact_match", exact_match ? "true" : ""}, {"order_by_date", order_by_date ? "true" : ""}, {"distro_series", ds ? ds.value().self_link : ""}, {"component_name", !component_name.empty() ? component_name : ""}, {"created_since_date", !created_since_date.empty() ? created_since_date : ""}, {"pocket", !pocket.empty() ? pocket : ""}, {"source_name", !source_name.empty() ? source_name : ""}, {"status", !status.empty() ? status : ""}, {"version", !version.empty() ? version : ""} }; params["ws.op"] = "getPublishedSources"; // Remove empty entries for (auto it = params.begin(); it != params.end(); ) { if (it->second.empty()) { it = params.erase(it); } else { ++it; } } std::cout << "Running a getPublishedSources() operation with " << self_link << "..." << std::endl; auto response = lp->api_get(self_link, params); if(!response) co_return; auto data = nlohmann::json::parse(response.value()); while (true) { 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(); } } if (!data.contains("next_collection_link") || data["next_collection_link"].is_null() || data["next_collection_link"] == "") break; response = lp->api_get(data["next_collection_link"].get()); if(!response) break; data = nlohmann::json::parse(response.value()); } } std::optional archive::checkUpload(const std::string& component, const std::string& distroseries, const std::string& person, const std::string& pocket, const std::string& sourcepackagename, bool strict_component) const { std::map params; params["ws.op"] = "checkUpload"; params["component"] = component; params["distroseries"] = distroseries; params["person"] = person; params["pocket"] = pocket; params["sourcepackagename"] = sourcepackagename; if(strict_component) params["strict_component"] = "true"; auto response = lp->api_get(self_link, params); if(!response) return std::nullopt; return nlohmann::json::parse(response.value()); } std::optional archive::getArchiveDependency(const std::string& dependency_link) const { std::map params; params["ws.op"] = "getArchiveDependency"; params["dependency"] = dependency_link; auto response = lp->api_get(self_link, params); if(!response) return std::nullopt; auto ad_opt = archive_dependency::parse(response.value()); if(ad_opt) ad_opt->set_lp(lp); return ad_opt; } std::optional archive::getBuildCounters(bool include_needsbuild) const { std::map params; params["ws.op"] = "getBuildCounters"; if(include_needsbuild) params["include_needsbuild"]="true"; auto response = lp->api_get(self_link, params); if(!response) return std::nullopt; return nlohmann::json::parse(response.value()); } std::generator archive::getBuildRecords(const std::string build_state, const std::string pocket, const std::string source_name) const { std::map params; params["ws.op"] = "getBuildRecords"; if(!build_state.empty()) params["build_state"] = build_state; if(!pocket.empty()) params["pocket"] = pocket; if(!source_name.empty()) params["source_name"] = source_name; auto response = lp->api_get(self_link, params); if(!response) co_return; auto data = nlohmann::json::parse(response.value()); while (true) { if (data.contains("entries") && data["entries"].is_array()) { for (auto& e : data["entries"]) { auto b_opt = build::parse(e.dump()); if(!b_opt) continue; b_opt->set_lp(lp); co_yield b_opt.value(); } } if(!data.contains("next_collection_link") || data["next_collection_link"].is_null() || data["next_collection_link"]=="") break; response = lp->api_get(data["next_collection_link"].get()); if(!response) break; data = nlohmann::json::parse(response.value()); } } std::optional archive::getBuildSummariesForSourceIds(const std::vector& source_ids) const { std::map params; params["ws.op"] = "getBuildSummariesForSourceIds"; std::string joined; for (auto &sid : source_ids) { joined += sid + ","; } if(!joined.empty()) joined.pop_back(); if(!joined.empty()) params["source_ids"] = joined; auto response = lp->api_get(self_link, params); if(!response) return std::nullopt; return nlohmann::json::parse(response.value()); } std::generator archive::getComponentsForQueueAdmin(const std::string& person_link) const { std::map params; params["ws.op"] = "getComponentsForQueueAdmin"; params["person"] = person_link; auto response = lp->api_get(self_link, params); if(!response) co_return; auto data = nlohmann::json::parse(response.value()); if(data.contains("entries") && data["entries"].is_array()){ for(auto& e : data["entries"]){ auto ap = archive_permission::parse(e.dump()); if(ap) { ap->set_lp(lp); co_yield ap.value(); } } } } std::optional archive::getNamedAuthToken(const std::string& name) const { std::map params; params["ws.op"]="getNamedAuthToken"; params["name"]=name; auto response = lp->api_get(self_link, params); if(!response) return std::nullopt; return nlohmann::json::parse(response.value()); } std::optional archive::getNamedAuthTokens(const std::vector& names) const { std::map params; params["ws.op"]="getNamedAuthTokens"; if(!names.empty()){ std::string joined; for(auto& n:names) joined+=n+","; if(!joined.empty()) joined.pop_back(); params["names"]=joined; } auto response = lp->api_get(self_link, params); if(!response) return std::nullopt; return nlohmann::json::parse(response.value()); } std::generator archive::getPackagesetsForSource(const std::string& sourcepackagename, bool direct_permissions) const { std::map params; params["ws.op"]="getPackagesetsForSource"; params["sourcepackagename"]=sourcepackagename; if(direct_permissions) params["direct_permissions"]="true"; auto response=lp->api_get(self_link, params); if(!response) co_return; auto data=nlohmann::json::parse(response.value()); if(data.contains("entries") && data["entries"].is_array()){ for(auto&e: data["entries"]){ auto ap=archive_permission::parse(e.dump()); if(ap) {ap->set_lp(lp); co_yield ap.value();} } } } std::generator archive::getPackagesetsForSourceUploader(const std::string& person_link, const std::string& sourcepackagename) const { std::map params; params["ws.op"]="getPackagesetsForSourceUploader"; params["person"]=person_link; params["sourcepackagename"]=sourcepackagename; auto response=lp->api_get(self_link, params); if(!response) co_return; auto data=nlohmann::json::parse(response.value()); if(data.contains("entries")&&data["entries"].is_array()){ for(auto&e:data["entries"]){ auto ap=archive_permission::parse(e.dump()); if(ap){ap->set_lp(lp);co_yield ap.value();} } } } std::generator archive::getPackagesetsForUploader(const std::string& person_link) const { std::map params; params["ws.op"]="getPackagesetsForUploader"; params["person"]=person_link; auto response=lp->api_get(self_link,params); if(!response) co_return; auto data=nlohmann::json::parse(response.value()); if(data.contains("entries") && data["entries"].is_array()){ for(auto&e:data["entries"]){ auto ap=archive_permission::parse(e.dump()); if(ap){ap->set_lp(lp);co_yield ap.value();} } } } std::generator archive::getPermissionsForPerson(const std::string& person_link) const { std::map params; params["ws.op"]="getPermissionsForPerson"; params["person"]=person_link; auto response=lp->api_get(self_link,params); if(!response) co_return; auto data=nlohmann::json::parse(response.value()); if(data.contains("entries")){ for(auto&e:data["entries"]){ auto ap=archive_permission::parse(e.dump()); if(ap){ap->set_lp(lp);co_yield ap.value();} } } } std::generator archive::getPocketsForQueueAdmin(const std::string& person_link) const { std::mapparams; params["ws.op"]="getPocketsForQueueAdmin"; params["person"]=person_link; auto response=lp->api_get(self_link,params); if(!response) co_return; auto data=nlohmann::json::parse(response.value()); if(data.contains("entries")){ for(auto&e:data["entries"]){ auto ap=archive_permission::parse(e.dump()); if(ap){ap->set_lp(lp);co_yield ap.value();} } } } std::generator archive::getPocketsForUploader(const std::string& person_link) const { std::mapparams; params["ws.op"]="getPocketsForUploader"; params["person"]=person_link; auto response=lp->api_get(self_link,params); if(!response) co_return; auto data=nlohmann::json::parse(response.value()); if(data.contains("entries")){ for(auto&e:data["entries"]){ auto ap=archive_permission::parse(e.dump()); if(ap){ap->set_lp(lp);co_yield ap.value();} } } } std::generator archive::getPublishedBinaries(const std::string& binary_name, const std::string& component_name, const std::string& created_since_date, const std::string& distro_arch_series, bool exact_match, bool order_by_date, bool ordered, const std::string& pocket, const std::string& status, const std::string& version) const { std::map params; params["ws.op"]="getPublishedBinaries"; if(!binary_name.empty()) params["binary_name"]=binary_name; if(!component_name.empty()) params["component_name"]=component_name; if(!created_since_date.empty()) params["created_since_date"]=created_since_date; if(!distro_arch_series.empty()) params["distro_arch_series"]=distro_arch_series; if(exact_match) params["exact_match"]="true"; if(order_by_date) params["order_by_date"]="true"; if(!ordered) params["ordered"]="false"; if(!pocket.empty()) params["pocket"]=pocket; if(!status.empty()) params["status"]=status; if(!version.empty()) params["version"]=version; auto response=lp->api_get(self_link,params); if(!response) co_return; auto data=nlohmann::json::parse(response.value()); while(true){ if(data.contains("entries") && data["entries"].is_array()){ for(auto&e:data["entries"]){ auto bpph = binary_package_publishing_history::parse(e.dump()); if(bpph){bpph->set_lp(lp);co_yield bpph.value();} } } if(!data.contains("next_collection_link")||data["next_collection_link"].is_null()||data["next_collection_link"]=="")break; response=lp->api_get(data["next_collection_link"].get()); if(!response)break; data=nlohmann::json::parse(response.value()); } } std::generator archive::getQueueAdminsForComponent(const std::string& component_name) const { std::mapparams; params["ws.op"]="getQueueAdminsForComponent"; params["component_name"]=component_name; auto response=lp->api_get(self_link,params); if(!response)co_return; auto data=nlohmann::json::parse(response.value()); if(data.contains("entries")){ for(auto&e:data["entries"]){ auto ap=archive_permission::parse(e.dump()); if(ap){ap->set_lp(lp); co_yield ap.value();} } } } std::generator archive::getQueueAdminsForPocket(const std::string& distroseries, const std::string& pocket) const { std::mapparams; params["ws.op"]="getQueueAdminsForPocket"; params["distroseries"]=distroseries; params["pocket"]=pocket; auto response=lp->api_get(self_link,params); if(!response)co_return; auto data=nlohmann::json::parse(response.value()); if(data.contains("entries")){ for(auto&e:data["entries"]){ auto ap=archive_permission::parse(e.dump()); if(ap){ap->set_lp(lp);co_yield ap.value();} } } } std::optional archive::getSigningKeyData() const { std::mapparams; params["ws.op"]="getSigningKeyData"; auto response=lp->api_get(self_link,params); if(!response) return std::nullopt; auto j=nlohmann::json::parse(response.value()); if(j.is_string()) return j.get(); return std::nullopt; } std::generator archive::getUploadersForComponent(const std::string& component_name) const { std::mapparams; params["ws.op"]="getUploadersForComponent"; if(!component_name.empty()) params["component_name"]=component_name; auto response=lp->api_get(self_link,params); if(!response) co_return; auto data=nlohmann::json::parse(response.value()); if(data.contains("entries")){ for(auto&e:data["entries"]){ auto ap=archive_permission::parse(e.dump()); if(ap){ap->set_lp(lp);co_yield ap.value();} } } } std::generator archive::getUploadersForPackage(const std::string& source_package_name) const { std::mapparams; params["ws.op"]="getUploadersForPackage"; params["source_package_name"]=source_package_name; auto response=lp->api_get(self_link,params); if(!response)co_return; auto data=nlohmann::json::parse(response.value()); if(data.contains("entries")){ for(auto&e:data["entries"]){ auto ap=archive_permission::parse(e.dump()); if(ap){ap->set_lp(lp);co_yield ap.value();} } } } std::generator archive::getUploadersForPackageset(const std::string& packageset, bool direct_permissions) const { std::mapparams; params["ws.op"]="getUploadersForPackageset"; params["packageset"]=packageset; if(direct_permissions) params["direct_permissions"]="true"; auto response=lp->api_get(self_link,params); if(!response) co_return; auto data=nlohmann::json::parse(response.value()); if(data.contains("entries")){ for(auto&e:data["entries"]){ auto ap=archive_permission::parse(e.dump()); if(ap){ap->set_lp(lp);co_yield ap.value();} } } } std::generator archive::getUploadersForPocket(const std::string& pocket) const { std::mapparams; params["ws.op"]="getUploadersForPocket"; params["pocket"]=pocket; auto response=lp->api_get(self_link,params); if(!response)co_return; auto data=nlohmann::json::parse(response.value()); if(data.contains("entries")){ for(auto&e:data["entries"]){ auto ap=archive_permission::parse(e.dump()); if(ap){ap->set_lp(lp);co_yield ap.value();} } } } std::optional archive::isSourceUploadAllowed(const std::string& distroseries, const std::string& person, const std::string& sourcepackagename) const { std::map params; params["ws.op"]="isSourceUploadAllowed"; params["distroseries"]=distroseries; params["person"]=person; params["sourcepackagename"]=sourcepackagename; auto response=lp->api_get(self_link,params); if(!response)return std::nullopt; auto j=nlohmann::json::parse(response.value()); if(j.is_boolean()) return j.get(); return std::nullopt; } std::optional archive::addArchiveDependency(const std::string& dependency_link, const std::string& component, const std::string& pocket) const { std::mapparams; params["ws.op"]="addArchiveDependency"; params["dependency"]=dependency_link; if(!component.empty()) params["component"]=component; params["pocket"]=pocket; auto response=lp->api_post(self_link,params); if(!response) return std::nullopt; auto ad=archive_dependency::parse(response.value()); if(ad) ad->set_lp(lp); return ad; } bool archive::copyPackage(const std::string& from_archive, const std::string& from_pocket, const std::string& from_series, bool include_binaries, bool move, std::optional phased_update_percentage, bool silent, const std::string& source_name, const std::string& sponsored, const std::string& to_pocket, const std::string& to_series, bool unembargo, const std::string& version, bool auto_approve) const { std::mapparams; params["ws.op"]="copyPackage"; params["from_archive"]=from_archive; if(!from_pocket.empty())params["from_pocket"]=from_pocket; if(!from_series.empty())params["from_series"]=from_series; if(include_binaries)params["include_binaries"]="true"; if(move)params["move"]="true"; if(phased_update_percentage.has_value())params["phased_update_percentage"]=std::to_string(phased_update_percentage.value()); if(silent)params["silent"]="true"; params["source_name"]=source_name; if(!sponsored.empty()) params["sponsored"]=sponsored; params["to_pocket"]=to_pocket; if(!to_series.empty())params["to_series"]=to_series; if(unembargo)params["unembargo"]="true"; params["version"]=version; if(auto_approve)params["auto_approve"]="true"; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::copyPackages(const std::string& from_archive, const std::string& from_series, bool include_binaries, bool silent, const std::vector& source_names, const std::string& sponsored, const std::string& to_pocket, const std::string& to_series, bool unembargo, bool auto_approve) const { std::map params; params["ws.op"]="copyPackages"; params["from_archive"]=from_archive; if(!from_series.empty()) params["from_series"]=from_series; if(include_binaries) params["include_binaries"]="true"; if(silent) params["silent"]="true"; { std::string joined; for(auto&s:source_names)joined+=s+","; if(!joined.empty())joined.pop_back(); if(!joined.empty()) params["source_names"]=joined; } if(!sponsored.empty()) params["sponsored"]=sponsored; params["to_pocket"]=to_pocket; if(!to_series.empty()) params["to_series"]=to_series; if(unembargo)params["unembargo"]="true"; if(auto_approve)params["auto_approve"]="true"; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::deleteComponentUploader(const std::string& component_name, const std::string& person) const { std::mapparams; params["ws.op"]="deleteComponentUploader"; params["component_name"]=component_name; params["person"]=person; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::deletePackageUploader(const std::string& person, const std::string& source_package_name) const { std::mapparams; params["ws.op"]="deletePackageUploader"; params["person"]=person; params["source_package_name"]=source_package_name; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::deletePackagesetUploader(const std::string& packageset, const std::string& person, bool explicit_) const { std::map params; params["ws.op"]="deletePackagesetUploader"; params["packageset"]=packageset; if(explicit_)params["explicit"]="true"; params["person"]=person; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::deletePocketQueueAdmin(const std::string& distroseries, const std::string& person, const std::string& pocket) const { std::mapparams; params["ws.op"]="deletePocketQueueAdmin"; if(!distroseries.empty())params["distroseries"]=distroseries; params["person"]=person; params["pocket"]=pocket; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::deletePocketUploader(const std::string& person, const std::string& pocket) const { std::mapparams; params["ws.op"]="deletePocketUploader"; params["person"]=person; params["pocket"]=pocket; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::deleteQueueAdmin(const std::string& component_name, const std::string& person) const { std::mapparams; params["ws.op"]="deleteQueueAdmin"; params["component_name"]=component_name; params["person"]=person; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::enableRestrictedProcessor(const std::string& processor) const { std::mapparams; params["ws.op"]="enableRestrictedProcessor"; params["processor"]=processor; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::markSuiteDirty(const std::string& distroseries, const std::string& pocket) const { std::mapparams; params["ws.op"]="markSuiteDirty"; params["distroseries"]=distroseries; params["pocket"]=pocket; auto resp=lp->api_post(self_link,params); return resp.has_value(); } std::optional archive::newComponentUploader(const std::string& component_name, const std::string& person) const { std::mapparams; params["ws.op"]="newComponentUploader"; params["component_name"]=component_name; params["person"]=person; auto resp=lp->api_post(self_link,params); if(!resp)return std::nullopt; auto ap=archive_permission::parse(resp.value()); if(ap)ap->set_lp(lp); return ap; } std::optional archive::newNamedAuthToken(const std::string& name, const std::optional& token) const { std::mapparams; params["ws.op"]="newNamedAuthToken"; params["name"]=name; if(token.has_value())params["token"]=token.value(); auto resp=lp->api_post(self_link,params); if(!resp)return std::nullopt; return nlohmann::json::parse(resp.value()); } std::optional archive::newNamedAuthTokens(const std::vector& names) const { std::mapparams; params["ws.op"]="newNamedAuthTokens"; if(!names.empty()){ std::string joined; for(auto&n:names)joined+=n+","; if(!joined.empty())joined.pop_back(); params["names"]=joined; } auto resp=lp->api_post(self_link,params); if(!resp)return std::nullopt; return nlohmann::json::parse(resp.value()); } std::optional archive::newPackageUploader(const std::string& person, const std::string& source_package_name) const { std::mapparams; params["ws.op"]="newPackageUploader"; params["person"]=person; params["source_package_name"]=source_package_name; auto resp=lp->api_post(self_link,params); if(!resp)return std::nullopt; auto ap=archive_permission::parse(resp.value()); if(ap)ap->set_lp(lp); return ap; } std::optional archive::newPackagesetUploader(const std::string& packageset, const std::string& person, bool explicit_) const { std::mapparams; params["ws.op"]="newPackagesetUploader"; params["packageset"]=packageset; if(explicit_)params["explicit"]="true"; params["person"]=person; auto resp=lp->api_post(self_link,params); if(!resp)return std::nullopt; auto ap=archive_permission::parse(resp.value()); if(ap)ap->set_lp(lp); return ap; } std::optional archive::newPocketQueueAdmin(const std::string& distroseries, const std::string& person, const std::string& pocket) const { std::mapparams; params["ws.op"]="newPocketQueueAdmin"; if(!distroseries.empty())params["distroseries"]=distroseries; params["person"]=person; params["pocket"]=pocket; auto resp=lp->api_post(self_link,params); if(!resp)return std::nullopt; auto ap=archive_permission::parse(resp.value()); if(ap)ap->set_lp(lp); return ap; } std::optional archive::newPocketUploader(const std::string& person, const std::string& pocket) const { std::mapparams; params["ws.op"]="newPocketUploader"; params["person"]=person; params["pocket"]=pocket; auto resp=lp->api_post(self_link,params); if(!resp)return std::nullopt; auto ap=archive_permission::parse(resp.value()); if(ap)ap->set_lp(lp); return ap; } std::optional archive::newQueueAdmin(const std::string& component_name, const std::string& person) const { std::mapparams; params["ws.op"]="newQueueAdmin"; params["component_name"]=component_name; params["person"]=person; auto resp=lp->api_post(self_link,params); if(!resp)return std::nullopt; auto ap=archive_permission::parse(resp.value()); if(ap)ap->set_lp(lp); return ap; } std::optional archive::newSubscription(const std::string& subscriber, const std::optional& date_expires, const std::optional& description) const { std::mapparams; params["ws.op"]="newSubscription"; params["subscriber"]=subscriber; if(date_expires.has_value()) params["date_expires"]=date_expires.value(); if(description.has_value()) params["description"]=description.value(); auto resp=lp->api_post(self_link,params); if(!resp)return std::nullopt; return nlohmann::json::parse(resp.value()); } bool archive::removeArchiveDependency(const std::string& dependency_link) const { std::mapparams; params["ws.op"]="removeArchiveDependency"; params["dependency"]=dependency_link; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::removeCopyNotification(const std::string& job_id) const { std::mapparams; params["ws.op"]="removeCopyNotification"; params["job_id"]=job_id; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::revokeNamedAuthToken(const std::string& name) const { std::mapparams; params["ws.op"]="revokeNamedAuthToken"; params["name"]=name; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::revokeNamedAuthTokens(const std::vector& names) const { std::mapparams; params["ws.op"]="revokeNamedAuthTokens"; if(!names.empty()){ std::string joined; for(auto&n:names)joined+=n+","; if(!joined.empty())joined.pop_back(); params["names"]=joined; } auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::setProcessors(const std::vector& processors) const { std::mapparams; params["ws.op"]="setProcessors"; { std::string joined; for(auto&p:processors)joined+=p+","; if(!joined.empty())joined.pop_back(); params["processors"]=joined; } auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::syncSource(const std::string& from_archive, bool include_binaries, const std::string& source_name, const std::string& to_pocket, const std::string& to_series, const std::string& version) const { std::mapparams; params["ws.op"]="syncSource"; params["from_archive"]=from_archive; if(include_binaries)params["include_binaries"]="true"; params["source_name"]=source_name; params["to_pocket"]=to_pocket; if(!to_series.empty())params["to_series"]=to_series; params["version"]=version; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::syncSources(const std::string& from_archive, const std::string& from_series, bool include_binaries, const std::vector& source_names, const std::string& to_pocket, const std::string& to_series) const { std::mapparams; params["ws.op"]="syncSources"; params["from_archive"]=from_archive; if(!from_series.empty())params["from_series"]=from_series; if(include_binaries)params["include_binaries"]="true"; { std::string joined; for(auto&s:source_names)joined+=s+","; if(!joined.empty())joined.pop_back(); if(!joined.empty()) params["source_names"]=joined; } params["to_pocket"]=to_pocket; if(!to_series.empty())params["to_series"]=to_series; auto resp=lp->api_post(self_link,params); return resp.has_value(); } bool archive::uploadCIBuild(const std::string& ci_build, const std::string& to_channel, const std::string& to_pocket, const std::string& to_series) const { std::mapparams; params["ws.op"]="uploadCIBuild"; params["ci_build"]=ci_build; if(!to_channel.empty())params["to_channel"]=to_channel; params["to_pocket"]=to_pocket; params["to_series"]=to_series; auto resp=lp->api_post(self_link,params); return resp.has_value(); }