From b1224b82b5b5ed381959ced8567fe10aab178d89 Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 2 Jul 2020 01:17:08 +0200 Subject: [PATCH] Use PR numbers instead of branch names to determine IDs. --- src/git.cpp | 42 +++---------------------- src/git.hpp | 4 --- src/gitea.cpp | 85 ++++++++++++++++++++++++++++++++++++++++----------- src/gitea.hpp | 18 ++++++++--- src/main.cpp | 15 ++++----- 5 files changed, 93 insertions(+), 71 deletions(-) diff --git a/src/git.cpp b/src/git.cpp index 5cfefc6..d0bd9eb 100644 --- a/src/git.cpp +++ b/src/git.cpp @@ -17,6 +17,7 @@ #include "git.hpp" #include "files.hpp" #include "fs-compat.hpp" +#include "gitea.hpp" #include "json.hpp" #include @@ -76,43 +77,9 @@ void clone() (files::get_tmpdir() / "repo").c_str(), &options)); } -uint64_t get_last_id() -{ - constexpr string_view branch_prefix{"web-"}; - uint64_t id{0}; - - git_branch_iterator *it; - if (git_branch_iterator_new(&it, _repo, GIT_BRANCH_REMOTE) == 0) - { - git_reference *ref; - git_branch_t type; - while (git_branch_next(&ref, &type, it) == 0) - { - const char *out{nullptr}; - git_branch_name(&out, ref); - const string branch_name{out}; - - size_t pos{branch_name.find(branch_prefix)}; - if (pos != string::npos) - { - pos += branch_prefix.size(); - uint64_t newid{stoull(branch_name.substr(pos))}; - if (newid > id) - { - id = newid; - } - } - git_reference_free(ref); - } - git_branch_iterator_free(it); - } - - return id; -} - void create_branch() { - const auto id{get_last_id() + 1}; + const auto id{gitea::get_last_pr_number() + 1}; const string branch_name = "web-" + std::to_string(id); const string ref_name{"refs/heads/" + branch_name}; git_oid oid_parent; @@ -134,7 +101,7 @@ void create_branch() void commit(const cgi::entry_type &entry) { // Write files. - const auto id{get_last_id() + 1}; + const auto id{gitea::get_last_pr_number() + 1}; const string basename{files::get_tmpdir() / "repo" / ("web-" + to_string(id))}; @@ -197,7 +164,8 @@ void push() { git_push_options options; git_remote *remote{nullptr}; - const string branch_name{"web-" + std::to_string(get_last_id() + 1)}; + const string branch_name{"web-" + + std::to_string(gitea::get_last_pr_number() + 1)}; string refspec_str{("refs/heads/" + branch_name)}; char *refspec = &refspec_str[0]; const git_strarray refspecs = {&refspec, 1}; diff --git a/src/git.hpp b/src/git.hpp index 9c16419..4afa25c 100644 --- a/src/git.hpp +++ b/src/git.hpp @@ -39,10 +39,6 @@ int cred_acquire(git_cred **cred, const char *url, // Clone the git repo. void clone(); -// FIXME: This will collapse when branches are deleted, use pull request IDs? -// Get highest branch-ID in use. -[[nodiscard]] uint64_t get_last_id(); - // Make a new branch for preparing the pull request. void create_branch(); diff --git a/src/gitea.cpp b/src/gitea.cpp index 3542e5b..bf257d2 100644 --- a/src/gitea.cpp +++ b/src/gitea.cpp @@ -17,10 +17,12 @@ #include "gitea.hpp" #include "cgi.hpp" -#include "curl/curl.h" #include "files.hpp" #include "json.hpp" +#include +#include + #include #include #include @@ -34,6 +36,8 @@ using std::string_view; using std::to_string; CURL *_connection; +string _curl_buffer_body; +uint64_t _last_pr_number{0}; void init() { @@ -63,7 +67,7 @@ void init() // Write the body into the void. // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) - curl_easy_setopt(_connection, CURLOPT_WRITEFUNCTION, noop_cb); + curl_easy_setopt(_connection, CURLOPT_WRITEFUNCTION, writer_body); } void cleanup() @@ -71,31 +75,55 @@ void cleanup() curl_easy_cleanup(gitea::_connection); } -size_t noop_cb(void * /*ptr*/, size_t size, size_t nmemb, void * /*data*/) +size_t writer_body(char *data, size_t size, size_t nmemb) { + if (data == nullptr) + { + return 0; + } + + _curl_buffer_body.append(data, size * nmemb); + return size * nmemb; } -void api_request(const string_view path, const string_view body) +string api_request(const http_method method, const string_view path, + const string_view body) { CURLcode code; - const string url{string("https://schlomp.space") += path}; + string url{string("https://schlomp.space") += path}; + _curl_buffer_body.clear(); + + switch (method) + { + case http_method::GET: + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + curl_easy_setopt(_connection, CURLOPT_HTTPGET, 1L); + url += body; + + break; + } + case http_method::POST: + { + // Prepare body to send. + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + curl_easy_setopt(_connection, CURLOPT_POSTFIELDSIZE, body.size()); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) + code = curl_easy_setopt(_connection, CURLOPT_POSTFIELDS, body.data()); + if (code != CURLE_OK) + { + throw runtime_error{"Couldn't set up data to send"}; + } + break; + } + } // 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"}; + throw runtime_error{"Couldn't set URL: " + to_string(code)}; } code = curl_easy_perform(_connection); @@ -107,16 +135,37 @@ void api_request(const string_view path, const string_view body) 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. + if (http_status < 200 || http_status >= 300) { throw runtime_error{"HTTP error: " + to_string(http_status)}; } + + return _curl_buffer_body; } void pull_request(const string_view branch, const cgi::entry_type &entry) { - api_request("/api/v1/repos/FediBlock/data/pulls", + api_request(http_method::POST, "/api/v1/repos/FediBlock/data/pulls", json::pull_request_body(branch, entry)); + ++_last_pr_number; +} + +uint64_t get_last_pr_number() +{ + if (_last_pr_number == 0) + { + const auto answer{api_request(http_method::GET, + "/api/v1/repos/FediBlock/data/pulls", + "?sort=recentupdate")}; + if (answer == "[]") + { + return 0; + } + const auto json{nlohmann::json::parse(answer)}; + _last_pr_number = json.front().front()["number"].get(); + } + + return _last_pr_number; } } // namespace FediBlock::gitea diff --git a/src/gitea.hpp b/src/gitea.hpp index 3a62ea6..cb008a8 100644 --- a/src/gitea.hpp +++ b/src/gitea.hpp @@ -20,14 +20,21 @@ #include "cgi.hpp" #include +#include #include namespace FediBlock::gitea { +using std::string; +using std::string_view; using std::uint64_t; -using std::string_view; +enum class http_method +{ + GET, + POST +}; // Initialize the curl connection handle. void init(); @@ -35,16 +42,17 @@ 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); +// Write HTTP response to string. +size_t writer_body(char *data, size_t size, size_t nmemb); // Make a HTTP POST request to the Gitea API. -void api_request(string_view path, string_view body); +string api_request(http_method method, 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(); +// Get number of last pull request. +[[nodiscard]] uint64_t get_last_pr_number(); } // namespace FediBlock::gitea diff --git a/src/main.cpp b/src/main.cpp index 2b6027e..8971b0d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -67,21 +67,22 @@ int main() const cgi::entry_type entry{cgi::parse_formdata()}; - print_debug(entry); + // print_debug(entry); git_libgit2_init(); + gitea::init(); git::clone(); git::create_branch(); git::commit(entry); git::push(); - cout << "Created branch: " - << "\r\n"; + gitea::pull_request("web-" + to_string(gitea::get_last_pr_number() + 1), + entry); - gitea::init(); - gitea::pull_request("web-" + to_string(git::get_last_id()), entry); + cout << "Created pull request: <" + << "https://schlomp.space/FediBlock/data/pulls/" + << gitea::get_last_pr_number() << ">\r\n"; try { @@ -92,8 +93,8 @@ int main() cerr << e.what() << '\n'; } - git_libgit2_shutdown(); gitea::cleanup(); + git_libgit2_shutdown(); return 0; }