Clean up everything.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
* More efficient. * More readable. * Errors are reported to the user.
This commit is contained in:
parent
a3fca80b29
commit
f522c9ae45
55
src/cgi.cpp
55
src/cgi.cpp
|
@ -46,41 +46,30 @@ using std::vector;
|
||||||
entry_type parse_formdata()
|
entry_type parse_formdata()
|
||||||
{
|
{
|
||||||
entry_type entry;
|
entry_type entry;
|
||||||
try
|
|
||||||
{
|
|
||||||
cgicc::Cgicc cgi;
|
|
||||||
entry.instance = cgi("instance");
|
|
||||||
entry.tags = string_to_vector(cgi("tags"));
|
|
||||||
entry.receipts = string_to_vector(cgi("receipts"));
|
|
||||||
entry.description = cgi("description");
|
|
||||||
|
|
||||||
const auto screenshot = cgi.getFile("screenshot");
|
cgicc::Cgicc cgi;
|
||||||
if (screenshot != cgi.getFiles().end())
|
entry.instance = cgi("instance");
|
||||||
|
entry.tags = string_to_vector(cgi("tags"));
|
||||||
|
entry.receipts = string_to_vector(cgi("receipts"));
|
||||||
|
entry.description = cgi("description");
|
||||||
|
|
||||||
|
const auto screenshot = cgi.getFile("screenshot");
|
||||||
|
if (screenshot != cgi.getFiles().end())
|
||||||
|
{
|
||||||
|
constexpr size_t size_limit{1024 * 1024 * 2}; // 2 MiB.
|
||||||
|
if (screenshot->getDataLength() > size_limit)
|
||||||
{
|
{
|
||||||
constexpr size_t size_limit{1024 * 1024 * 2}; // 2 MiB.
|
throw runtime_error{"Filesize too big"};
|
||||||
if (screenshot->getDataLength() > size_limit)
|
|
||||||
{
|
|
||||||
throw runtime_error{"Filesize too big"};
|
|
||||||
}
|
|
||||||
|
|
||||||
string filepath{files::get_tmpdir() / screenshot->getFilename()};
|
|
||||||
ofstream file{filepath, ios::binary};
|
|
||||||
if (file.good())
|
|
||||||
{
|
|
||||||
screenshot->writeToStream(file);
|
|
||||||
entry.screenshot_filepath = filepath;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw runtime_error{"Could not open temporary file: "
|
|
||||||
+ filepath};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (const exception &e)
|
const string filepath{files::get_tmpdir() / screenshot->getFilename()};
|
||||||
{
|
ofstream file{filepath, ios::binary};
|
||||||
cerr << e.what() << '\n';
|
if (!file.good())
|
||||||
// TODO: Make errors visible to the user in a helpful way.
|
{
|
||||||
|
throw runtime_error{"Could not open temporary file: " + filepath};
|
||||||
|
}
|
||||||
|
screenshot->writeToStream(file);
|
||||||
|
entry.screenshot_filepath = filepath;
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
|
@ -90,7 +79,7 @@ vector<string> string_to_vector(const string_view str)
|
||||||
{
|
{
|
||||||
vector<string> vec;
|
vector<string> vec;
|
||||||
|
|
||||||
stringstream input(str.data());
|
stringstream input{str.data()};
|
||||||
string element;
|
string element;
|
||||||
|
|
||||||
while (getline(input, element, ','))
|
while (getline(input, element, ','))
|
||||||
|
|
|
@ -76,7 +76,7 @@ fs::path get_datadir()
|
||||||
auto path{fs::path(env)};
|
auto path{fs::path(env)};
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
path /= ".local/share/fediblock-backend";
|
path /= ".local/share/fediblock-backend";
|
||||||
#elif defined(__unix__)
|
#else
|
||||||
path /= ".fediblock-backend";
|
path /= ".fediblock-backend";
|
||||||
#endif
|
#endif
|
||||||
fs::create_directories(path);
|
fs::create_directories(path);
|
||||||
|
@ -97,7 +97,7 @@ string get_access_token()
|
||||||
stringstream ss;
|
stringstream ss;
|
||||||
ss << file.rdbuf();
|
ss << file.rdbuf();
|
||||||
|
|
||||||
return ss.str().substr(0, ss.str().find('\n'));
|
return ss.str().substr(0, ss.str().find('\n')); // Remove trailing newline.
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace FediBlock::files
|
} // namespace FediBlock::files
|
||||||
|
|
|
@ -26,13 +26,13 @@ namespace FediBlock::files
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
// Creates and returns the temporary directory.
|
// Create and return the temporary directory.
|
||||||
[[nodiscard]] fs::path get_tmpdir();
|
[[nodiscard]] fs::path get_tmpdir();
|
||||||
|
|
||||||
// Remove the temporary directory. Throws runtime_error on error.
|
// Remove the temporary directory. Throws runtime_error on error.
|
||||||
void remove_tmpdir();
|
void remove_tmpdir();
|
||||||
|
|
||||||
// Returns the data directory and creates it if necessary.
|
// Return the data directory and create it if necessary.
|
||||||
[[nodiscard]] fs::path get_datadir();
|
[[nodiscard]] fs::path get_datadir();
|
||||||
|
|
||||||
// Read and return access token.
|
// Read and return access token.
|
||||||
|
|
35
src/git.cpp
35
src/git.cpp
|
@ -43,13 +43,13 @@ namespace FediBlock::git
|
||||||
|
|
||||||
using std::ofstream;
|
using std::ofstream;
|
||||||
using std::runtime_error;
|
using std::runtime_error;
|
||||||
using std::stoull;
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::string_view;
|
using std::string_view;
|
||||||
using std::to_string;
|
using std::to_string;
|
||||||
using std::uint64_t;
|
using std::uint64_t;
|
||||||
|
|
||||||
git_repository *_repo{nullptr};
|
git_repository *_repo{nullptr};
|
||||||
|
constexpr string_view _clone_url{"git@schlomp.space:FediBlock/data.git"};
|
||||||
|
|
||||||
void check(int error)
|
void check(int error)
|
||||||
{
|
{
|
||||||
|
@ -64,23 +64,24 @@ int cred_acquire(git_cred **cred, const char * /*url*/,
|
||||||
const char *username_from_url, unsigned int /*allowed_types*/,
|
const char *username_from_url, unsigned int /*allowed_types*/,
|
||||||
void * /*payload*/)
|
void * /*payload*/)
|
||||||
{
|
{
|
||||||
return git_credential_ssh_key_new(
|
const auto datadir{files::get_datadir()};
|
||||||
cred, username_from_url, (files::get_datadir() / "ssh_id.pub").c_str(),
|
|
||||||
(files::get_datadir() / "ssh_id").c_str(), nullptr);
|
return git_credential_ssh_key_new(cred, username_from_url,
|
||||||
|
(datadir / "ssh_id.pub").c_str(),
|
||||||
|
(datadir / "ssh_id").c_str(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clone()
|
void clone()
|
||||||
{
|
{
|
||||||
git_clone_options options = GIT_CLONE_OPTIONS_INIT;
|
git_clone_options options = GIT_CLONE_OPTIONS_INIT;
|
||||||
options.fetch_opts.callbacks.credentials = cred_acquire;
|
options.fetch_opts.callbacks.credentials = cred_acquire;
|
||||||
check(git_clone(&_repo, "git@schlomp.space:FediBlock/data.git",
|
check(git_clone(&_repo, _clone_url.data(),
|
||||||
(files::get_tmpdir() / "repo").c_str(), &options));
|
(files::get_tmpdir() / "repo").c_str(), &options));
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_branch()
|
void create_branch()
|
||||||
{
|
{
|
||||||
const auto id{gitea::get_last_pr_number() + 1};
|
const string branch_name{get_branch_name()};
|
||||||
const string branch_name = "web-" + std::to_string(id);
|
|
||||||
const string ref_name{"refs/heads/" + branch_name};
|
const string ref_name{"refs/heads/" + branch_name};
|
||||||
git_oid oid_parent;
|
git_oid oid_parent;
|
||||||
git_commit *commit;
|
git_commit *commit;
|
||||||
|
@ -101,14 +102,12 @@ void create_branch()
|
||||||
void commit(const cgi::entry_type &entry)
|
void commit(const cgi::entry_type &entry)
|
||||||
{
|
{
|
||||||
// Write files.
|
// Write files.
|
||||||
const auto id{gitea::get_last_pr_number() + 1};
|
const string basename{files::get_tmpdir() / "repo" / get_branch_name()};
|
||||||
const string basename{files::get_tmpdir() / "repo"
|
|
||||||
/ ("web-" + to_string(id))};
|
|
||||||
|
|
||||||
ofstream file(basename + ".json");
|
ofstream file(basename + ".json");
|
||||||
if (!file.good())
|
if (!file.good())
|
||||||
{
|
{
|
||||||
throw; // FIXME
|
throw runtime_error{"Could not create file: " + basename + ".json"};
|
||||||
}
|
}
|
||||||
file << json::to_json(entry);
|
file << json::to_json(entry);
|
||||||
file.close();
|
file.close();
|
||||||
|
@ -158,15 +157,15 @@ void commit(const cgi::entry_type &entry)
|
||||||
git_index_free(index);
|
git_index_free(index);
|
||||||
git_signature_free(sig);
|
git_signature_free(sig);
|
||||||
git_tree_free(tree);
|
git_tree_free(tree);
|
||||||
|
git_object_free(parent);
|
||||||
|
git_reference_free(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
void push()
|
void push()
|
||||||
{
|
{
|
||||||
git_push_options options;
|
git_push_options options;
|
||||||
git_remote *remote{nullptr};
|
git_remote *remote{nullptr};
|
||||||
const string branch_name{"web-"
|
string refspec_str{("refs/heads/" + get_branch_name())};
|
||||||
+ std::to_string(gitea::get_last_pr_number() + 1)};
|
|
||||||
string refspec_str{("refs/heads/" + branch_name)};
|
|
||||||
char *refspec = &refspec_str[0];
|
char *refspec = &refspec_str[0];
|
||||||
const git_strarray refspecs = {&refspec, 1};
|
const git_strarray refspecs = {&refspec, 1};
|
||||||
|
|
||||||
|
@ -175,6 +174,14 @@ void push()
|
||||||
options.callbacks.credentials = cred_acquire;
|
options.callbacks.credentials = cred_acquire;
|
||||||
|
|
||||||
check(git_remote_push(remote, &refspecs, &options));
|
check(git_remote_push(remote, &refspecs, &options));
|
||||||
|
|
||||||
|
git_remote_free(remote);
|
||||||
|
}
|
||||||
|
|
||||||
|
string get_branch_name()
|
||||||
|
{
|
||||||
|
const auto id{gitea::get_last_pr_number() + 1};
|
||||||
|
return "web-" + to_string(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace FediBlock::git
|
} // namespace FediBlock::git
|
||||||
|
|
|
@ -22,13 +22,15 @@
|
||||||
#include <git2.h>
|
#include <git2.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace FediBlock::git
|
namespace FediBlock::git
|
||||||
{
|
{
|
||||||
|
|
||||||
|
using std::string;
|
||||||
using std::uint64_t;
|
using std::uint64_t;
|
||||||
|
|
||||||
// Throws runtime_error on error.
|
// Throw runtime_error on error.
|
||||||
void check(int error);
|
void check(int error);
|
||||||
|
|
||||||
// Acquire credentials for SSH.
|
// Acquire credentials for SSH.
|
||||||
|
@ -48,6 +50,9 @@ void commit(const cgi::entry_type &entry);
|
||||||
// Push the new commit.
|
// Push the new commit.
|
||||||
void push();
|
void push();
|
||||||
|
|
||||||
|
// Get the name of the branch we use.
|
||||||
|
string get_branch_name();
|
||||||
|
|
||||||
} // namespace FediBlock::git
|
} // namespace FediBlock::git
|
||||||
|
|
||||||
#endif // FEDIBLOCK_BACKEND_GIT_HPP
|
#endif // FEDIBLOCK_BACKEND_GIT_HPP
|
||||||
|
|
|
@ -38,6 +38,8 @@ using std::to_string;
|
||||||
CURL *_connection;
|
CURL *_connection;
|
||||||
string _curl_buffer_body;
|
string _curl_buffer_body;
|
||||||
uint64_t _last_pr_number{0};
|
uint64_t _last_pr_number{0};
|
||||||
|
constexpr string_view _forge_baseurl{"https://schlomp.space"};
|
||||||
|
constexpr string_view _repo_name{"FediBlock/data"};
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
|
@ -65,7 +67,6 @@ void init()
|
||||||
throw runtime_error{"Could not add headers"};
|
throw runtime_error{"Could not add headers"};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the body into the void.
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
|
||||||
curl_easy_setopt(_connection, CURLOPT_WRITEFUNCTION, writer_body);
|
curl_easy_setopt(_connection, CURLOPT_WRITEFUNCTION, writer_body);
|
||||||
}
|
}
|
||||||
|
@ -91,7 +92,7 @@ string api_request(const http_method method, const string_view path,
|
||||||
const string_view body)
|
const string_view body)
|
||||||
{
|
{
|
||||||
CURLcode code;
|
CURLcode code;
|
||||||
string url{string("https://schlomp.space") += path};
|
string url{string(_forge_baseurl) += path};
|
||||||
_curl_buffer_body.clear();
|
_curl_buffer_body.clear();
|
||||||
|
|
||||||
switch (method)
|
switch (method)
|
||||||
|
@ -106,7 +107,6 @@ string api_request(const http_method method, const string_view path,
|
||||||
}
|
}
|
||||||
case http_method::POST:
|
case http_method::POST:
|
||||||
{
|
{
|
||||||
// Prepare body to send.
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
|
||||||
curl_easy_setopt(_connection, CURLOPT_POSTFIELDSIZE, body.size());
|
curl_easy_setopt(_connection, CURLOPT_POSTFIELDSIZE, body.size());
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
|
||||||
|
@ -145,7 +145,8 @@ string api_request(const http_method method, const string_view path,
|
||||||
|
|
||||||
void pull_request(const string_view branch, const cgi::entry_type &entry)
|
void pull_request(const string_view branch, const cgi::entry_type &entry)
|
||||||
{
|
{
|
||||||
api_request(http_method::POST, "/api/v1/repos/FediBlock/data/pulls",
|
api_request(http_method::POST,
|
||||||
|
(string("/api/v1/repos/") += _repo_name) += "/pulls",
|
||||||
json::pull_request_body(branch, entry));
|
json::pull_request_body(branch, entry));
|
||||||
++_last_pr_number;
|
++_last_pr_number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ using std::string_view;
|
||||||
// Convert an entry_type into a JSON string.
|
// Convert an entry_type into a JSON string.
|
||||||
[[nodiscard]] string to_json(const cgi::entry_type &entry);
|
[[nodiscard]] string to_json(const cgi::entry_type &entry);
|
||||||
|
|
||||||
|
// Return the body for a pull request.
|
||||||
[[nodiscard]] string pull_request_body(string_view branch,
|
[[nodiscard]] string pull_request_body(string_view branch,
|
||||||
const cgi::entry_type &entry);
|
const cgi::entry_type &entry);
|
||||||
|
|
||||||
|
|
|
@ -50,12 +50,11 @@ int main()
|
||||||
git::commit(entry);
|
git::commit(entry);
|
||||||
git::push();
|
git::push();
|
||||||
|
|
||||||
gitea::pull_request("web-" + to_string(gitea::get_last_pr_number() + 1),
|
gitea::pull_request(git::get_branch_name(), entry);
|
||||||
entry);
|
|
||||||
|
|
||||||
cout << "Created pull request: <"
|
cout << "Created pull request: <"
|
||||||
<< "https://schlomp.space/FediBlock/data/pulls/"
|
<< "https://schlomp.space/FediBlock/data/pulls/"
|
||||||
<< gitea::get_last_pr_number() << ">\r\n";
|
<< gitea::get_last_pr_number() << ">.\r\n";
|
||||||
|
|
||||||
files::remove_tmpdir();
|
files::remove_tmpdir();
|
||||||
}
|
}
|
||||||
|
@ -63,6 +62,8 @@ int main()
|
||||||
{
|
{
|
||||||
cerr << e.what() << '\n';
|
cerr << e.what() << '\n';
|
||||||
cout << "An error happened: " << e.what() << "\r\n";
|
cout << "An error happened: " << e.what() << "\r\n";
|
||||||
|
cout << "Please report it at "
|
||||||
|
"<https://schlomp.space/FediBlock/backend/issues>.\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
gitea::cleanup();
|
gitea::cleanup();
|
||||||
|
|
Reference in New Issue