From 24d9e419fa3747c65117177814d863369c027141 Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 2 Jul 2020 00:19:18 +0200 Subject: [PATCH] Add pull requests via Gitea API. --- .drone.yml | 6 +-- CMakeLists.txt | 1 + CREDITS | 5 ++ src/CMakeLists.txt | 7 ++- src/gitea.cpp | 122 +++++++++++++++++++++++++++++++++++++++++++ src/gitea.hpp | 51 ++++++++++++++++++ src/main.cpp | 7 +++ tests/CMakeLists.txt | 7 ++- 8 files changed, 201 insertions(+), 5 deletions(-) create mode 100644 src/gitea.cpp create mode 100644 src/gitea.hpp diff --git a/.drone.yml b/.drone.yml index f800e61..4d8dbc4 100644 --- a/.drone.yml +++ b/.drone.yml @@ -26,7 +26,7 @@ steps: - alias apt-get='rm -f /var/cache/apt/archives/lock && apt-get' - apt-get update -q - apt-get install -qq build-essential cmake g++-10 clang pkg-config - - apt-get install -qq catch libcgicc-dev nlohmann-json3-dev libgit2-dev + - apt-get install -qq catch libcgicc-dev nlohmann-json3-dev libgit2-dev libcurl4-openssl-dev - rm -rf build && mkdir -p build && cd build - cmake -G "Unix Makefiles" -DWITH_TESTS=YES .. - make VERBOSE=1 @@ -62,7 +62,7 @@ steps: - alias apt-get='rm -f /var/cache/apt/archives/lock && apt-get' - apt-get update -q - apt-get install -qq build-essential cmake clang pkg-config - - apt-get install -qq catch libcgicc-dev nlohmann-json-dev libgit2-dev + - apt-get install -qq catch libcgicc-dev nlohmann-json-dev libgit2-dev libcurl4-openssl-dev - rm -rf build && mkdir -p build && cd build - cmake -G "Unix Makefiles" -DWITH_TESTS=YES .. - make VERBOSE=1 @@ -92,7 +92,7 @@ steps: # - alias apt-get='rm -f /var/cache/apt/archives/lock && apt-get' # - apt-get update -q # - apt-get install -qq build-essential cmake clang pkg-config -# - apt-get install -qq catch libcgicc-dev nlohmann-json-dev libgit2-dev +# - apt-get install -qq catch libcgicc-dev nlohmann-json-dev libgit2-dev libcurl4-openssl-dev # - rm -rf build && mkdir -p build && cd build # - cmake -G "Unix Makefiles" -DWITH_TESTS=YES .. # - make VERBOSE=1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 80ada31..021a144 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ pkg_check_modules(cgicc REQUIRED IMPORTED_TARGET cgicc) find_package(nlohmann_json REQUIRED CONFIG) find_package(Filesystem REQUIRED COMPONENTS Final Experimental) pkg_check_modules(libgit2 REQUIRED IMPORTED_TARGET libgit2) +find_package(CURL 7.56 REQUIRED) add_subdirectory(src) diff --git a/CREDITS b/CREDITS index 1b0bad9..029e3b3 100644 --- a/CREDITS +++ b/CREDITS @@ -29,3 +29,8 @@ FediBlock-backend makes direct use of the following libraries and programs: From: libgit2 project and community https://libgit2.org/ License: GPL-2.0 with Linking Exception + + curl + From: Daniel Stenberg and community + https://curl.haxx.se/ + License: curl diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5be332b..cac3fa4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,7 +15,12 @@ target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(${PROJECT_NAME} - PRIVATE PkgConfig::cgicc nlohmann_json std::filesystem PkgConfig::libgit2) + PRIVATE + PkgConfig::cgicc + nlohmann_json + std::filesystem + PkgConfig::libgit2 + CURL::libcurl) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") diff --git a/src/gitea.cpp b/src/gitea.cpp new file mode 100644 index 0000000..3542e5b --- /dev/null +++ b/src/gitea.cpp @@ -0,0 +1,122 @@ +/* This file is part of FediBlock-backend. + * Copyright © 2020 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3. + * + * 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "gitea.hpp" + +#include "cgi.hpp" +#include "curl/curl.h" +#include "files.hpp" +#include "json.hpp" + +#include +#include +#include + +namespace FediBlock::gitea +{ + +using std::runtime_error; +using std::string; +using std::string_view; +using std::to_string; + +CURL *_connection; + +void init() +{ + _connection = curl_easy_init(); + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + CURLcode code{curl_easy_setopt(_connection, CURLOPT_FOLLOWLOCATION, 1L)}; + if (code != CURLE_OK) + { + throw runtime_error{"HTTP is not supported."}; + } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + curl_easy_setopt(_connection, CURLOPT_MAXREDIRS, 5L); + + // Add extra headers. + struct curl_slist *headers{nullptr}; + string authheader{"Authorization: token " + files::get_access_token()}; + headers = curl_slist_append(headers, authheader.c_str()); + headers = curl_slist_append(headers, "Accept: application/json"); + headers = curl_slist_append(headers, "Content-Type: application/json"); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + code = curl_easy_setopt(_connection, CURLOPT_HTTPHEADER, headers); + if (code != CURLE_OK) + { + throw runtime_error{"Could not add headers"}; + } + + // Write the body into the void. + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + curl_easy_setopt(_connection, CURLOPT_WRITEFUNCTION, noop_cb); +} + +void cleanup() +{ + curl_easy_cleanup(gitea::_connection); +} + +size_t noop_cb(void * /*ptr*/, size_t size, size_t nmemb, void * /*data*/) +{ + return size * nmemb; +} + +void api_request(const string_view path, const string_view body) +{ + CURLcode code; + const string url{string("https://schlomp.space") += path}; + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + code = curl_easy_setopt(_connection, CURLOPT_URL, url.c_str()); + if (code != CURLE_OK) + { + throw runtime_error{"Couldn't set URL"}; + } + + // Prepare body to send. + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + curl_easy_setopt(_connection, CURLOPT_POSTFIELDSIZE, body.size()); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + curl_easy_setopt(_connection, CURLOPT_POSTFIELDS, body.data()); + if (code != CURLE_OK) + { + throw runtime_error{"Couldn't set up data to send"}; + } + + code = curl_easy_perform(_connection); + if (code != CURLE_OK) + { + throw runtime_error{"libcurl error: " + to_string(code)}; + } + + long http_status; // NOLINT(google-runtime-int) + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + curl_easy_getinfo(_connection, CURLINFO_RESPONSE_CODE, &http_status); + if (http_status != 201) // 201 == Created. + { + throw runtime_error{"HTTP error: " + to_string(http_status)}; + } +} + +void pull_request(const string_view branch, const cgi::entry_type &entry) +{ + api_request("/api/v1/repos/FediBlock/data/pulls", + json::pull_request_body(branch, entry)); +} + +} // namespace FediBlock::gitea diff --git a/src/gitea.hpp b/src/gitea.hpp new file mode 100644 index 0000000..3a62ea6 --- /dev/null +++ b/src/gitea.hpp @@ -0,0 +1,51 @@ +/* This file is part of FediBlock-backend. + * Copyright © 2020 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3. + * + * 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef FEDIBLOCK_BACKEND_GITEA_HPP +#define FEDIBLOCK_BACKEND_GITEA_HPP + +#include "cgi.hpp" + +#include +#include + +namespace FediBlock::gitea +{ + +using std::uint64_t; + +using std::string_view; + +// Initialize the curl connection handle. +void init(); + +// Clean up the curl connection handle. +void cleanup(); + +// No-op write function. Discards HTTP response bodies. +size_t noop_cb(void *ptr, size_t size, size_t nmemb, void *data); + +// Make a HTTP POST request to the Gitea API. +void api_request(string_view path, string_view body); + +// Make a pull request. +void pull_request(string_view branch, const cgi::entry_type &entry); + +[[nodiscard]] uint64_t get_last_pr_id(); + +} // namespace FediBlock::gitea + +#endif // FEDIBLOCK_BACKEND_GITEA_HPP diff --git a/src/main.cpp b/src/main.cpp index f4be7f2..2b6027e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,16 +18,19 @@ #include "files.hpp" #include "fs-compat.hpp" #include "git.hpp" +#include "gitea.hpp" #include "json.hpp" #include #include #include +#include using std::cerr; using std::cout; using std::exception; +using std::to_string; using namespace FediBlock; @@ -77,6 +80,9 @@ int main() << "\r\n"; + gitea::init(); + gitea::pull_request("web-" + to_string(git::get_last_id()), entry); + try { files::remove_tmpdir(); @@ -87,6 +93,7 @@ int main() } git_libgit2_shutdown(); + gitea::cleanup(); return 0; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2679ace..204320f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,7 +9,12 @@ target_include_directories(${PROJECT_NAME}_testlib "$") target_link_libraries(${PROJECT_NAME}_testlib - PUBLIC PkgConfig::cgicc nlohmann_json std::filesystem PkgConfig::libgit2) + PUBLIC + PkgConfig::cgicc + nlohmann_json + std::filesystem + PkgConfig::libgit2 + CURL::libcurl) file(GLOB sources_tests test_*.cpp)