diff options
Diffstat (limited to 'backend/slackpkg.cpp')
| -rw-r--r-- | backend/slackpkg.cpp | 186 |
1 files changed, 72 insertions, 114 deletions
diff --git a/backend/slackpkg.cpp b/backend/slackpkg.cpp index c240088..4119625 100644 --- a/backend/slackpkg.cpp +++ b/backend/slackpkg.cpp @@ -11,13 +11,14 @@ module; #include <cstdint> #include <cstddef> #include <string.h> -#include <gio/gio.h> #include <curl/curl.h> #include <string> #include <regex> #include <vector> #include <forward_list> #include <filesystem> +#include <boost/algorithm/string.hpp> +#include <fstream> export module katja.slackpkg; @@ -72,18 +73,16 @@ public: CURL *curl = nullptr; cache_entry source_dest; std::forward_list<cache_entry> file_list; - GFile *tmp_dir, *repo_tmp_dir; /* Create the temporary directory for the repository */ - tmp_dir = g_file_new_for_path(tmpl.native().c_str()); - repo_tmp_dir = g_file_get_child(tmp_dir, this->name.c_str()); - g_file_make_directory(repo_tmp_dir, nullptr, nullptr); + std::filesystem::path tmp_dir = tmpl / this->name; + std::filesystem::create_directories(tmp_dir); /* Download PACKAGES.TXT. These files are most important, break if some of them couldn't be found */ for (const std::string& current_priority : this->priority) { source_dest.first = this->mirror + current_priority + "/PACKAGES.TXT"; - source_dest.second = tmpl / this->name / "PACKAGES.TXT"; + source_dest.second = tmp_dir / "PACKAGES.TXT"; if (get_file(&curl, source_dest.first.c_str(), std::nullopt) == CURLE_OK) { @@ -104,9 +103,6 @@ public: } } out: - g_object_unref(repo_tmp_dir); - g_object_unref(tmp_dir); - if (curl) { curl_easy_cleanup(curl); @@ -127,23 +123,19 @@ public: void generate_cache(JobData *job_data, const std::filesystem::path& tmpl) noexcept { std::vector<std::string> pkg_tokens; - char *query = nullptr, *filename = nullptr, *location = nullptr, *summary = nullptr, *line; + char *query = nullptr; unsigned pkg_compressed = 0, pkg_uncompressed = 0; std::uint8_t pkg_name_len; - GString *desc; - GFile *list_file; - GFileInputStream *fin = nullptr; - GDataInputStream *data_in = nullptr; + std::string desc, line, location; sqlite3_stmt *insert_statement = nullptr, *update_statement = nullptr, *insert_default_statement = nullptr; sqlite3_stmt *statement; + std::optional<std::string> filename, summary; /* Check if the temporary directory for this repository exists, then the file metadata have to be generated */ std::filesystem::path packages_txt = tmpl / this->name / "PACKAGES.TXT"; - list_file = g_file_new_for_path(packages_txt.native().c_str()); - fin = g_file_read(list_file, nullptr, nullptr); - g_object_unref(list_file); + std::ifstream data_in(packages_txt); - if (!fin) + if (!data_in) { goto out; } @@ -201,64 +193,63 @@ public: goto out; } - data_in = g_data_input_stream_new(G_INPUT_STREAM(fin)); - desc = g_string_new(""); + desc = ""; sqlite3_exec(job_data->db, "BEGIN TRANSACTION", nullptr, nullptr, nullptr); - while ((line = g_data_input_stream_read_line(data_in, nullptr, nullptr, nullptr))) + while (std::getline(data_in, line)) { - if (!strncmp(line, "PACKAGE NAME: ", 15)) + if (boost::starts_with(line, "PACKAGE NAME: ")) { - filename = g_strdup(line + 15); - if (this->is_blacklisted(filename)) + filename = line.substr(15); + if (this->is_blacklisted(filename.value())) { - g_free(filename); - filename = nullptr; + filename.reset(); } } - else if (filename && !strncmp(line, "PACKAGE LOCATION: ", 19)) + else if (filename.has_value() && boost::starts_with(line, "PACKAGE LOCATION: ")) { - location = g_strdup(line + 21); /* Exclude ./ at the path beginning */ + location = line.substr(21); /* Exclude ./ at the path beginning */ } - else if (filename && !strncmp(line, "PACKAGE SIZE (compressed): ", 28)) + else if (filename.has_value() && boost::starts_with(line, "PACKAGE SIZE (compressed): ")) { /* Remove the unit (kilobytes) */ - pkg_compressed = atoi(g_strndup(line + 28, strlen(line + 28) - 2)) * 1024; + std::from_chars(line.c_str() + 28, line.c_str() + line.size() - 2, pkg_compressed); + pkg_compressed *= 1024; } - else if (filename && !strncmp(line, "PACKAGE SIZE (uncompressed): ", 30)) + else if (filename.has_value() && boost::starts_with(line, "PACKAGE SIZE (uncompressed): ")) { /* Remove the unit (kilobytes) */ - pkg_uncompressed = atoi(g_strndup(line + 30, strlen(line + 30) - 2)) * 1024; + std::from_chars(line.c_str() + 30, line.c_str() + line.size() - 2, pkg_uncompressed); + pkg_uncompressed *= 1024; } - else if (filename && !g_strcmp0(line, "PACKAGE DESCRIPTION:")) + else if (filename.has_value() && boost::starts_with(line, "PACKAGE DESCRIPTION:")) { - g_free(line); - line = g_data_input_stream_read_line(data_in, nullptr, nullptr, nullptr); /* Short description */ + std::getline(data_in, line); - summary = g_strstr_len(line, -1, "("); - if (summary) /* Else summary = nullptr */ + auto summary_position = line.find_first_of('('); + if (summary_position != std::string::npos) /* Else summary = nullptr */ { - summary = g_strndup(summary + 1, strlen(summary) - 2); /* Without ( ) */ + summary = line.substr(summary_position + 1, line.size() - summary_position - 2); /* Without ( ) */ } - pkg_tokens = split_package_name(filename).value(); + pkg_tokens = split_package_name(filename.value()).value(); pkg_name_len = pkg_tokens[0].size(); /* Description begins with pkg_name: */ } - else if (filename && !strncmp(line, pkg_tokens[0].c_str(), pkg_name_len)) + else if (filename.has_value() && boost::starts_with(line, pkg_tokens[0])) { - g_string_append(desc, line + pkg_name_len + 1); + desc += line.substr(pkg_name_len + 1); } - else if (filename && !g_strcmp0(line, "")) + else if (filename.has_value() && line == "") { - if (g_strcmp0(location, "patches/packages")) /* Insert a new package */ + if (location != "patches/packages") /* Insert a new package */ { /* Get the package group based on its location */ - const char *cat = g_strrstr(location, "/"); - if (cat) + auto category_position = location.find_last_of('/'); + if (category_position != std::string::npos) { - ++cat; statement = insert_statement; - sqlite3_bind_text(insert_statement, 12, cat, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(insert_statement, 12, + location.c_str() + category_position + 1, -1, SQLITE_TRANSIENT); } else { @@ -274,9 +265,10 @@ public: sqlite3_bind_text(statement, 2, pkg_tokens[1].c_str(), -1, SQLITE_TRANSIENT); sqlite3_bind_text(statement, 3, pkg_tokens[2].c_str(), -1, SQLITE_TRANSIENT); sqlite3_bind_text(statement, 4, pkg_tokens[4].c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_text(statement, 5, location, -1, SQLITE_TRANSIENT); - sqlite3_bind_text(statement, 6, summary, -1, SQLITE_TRANSIENT); - sqlite3_bind_text(statement, 7, desc->str, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(statement, 5, location.c_str(), -1, SQLITE_TRANSIENT); + sqlite3_bind_text(statement, 6, + summary.has_value() ? summary.value().c_str() : nullptr, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(statement, 7, desc.c_str(), -1, SQLITE_TRANSIENT); sqlite3_bind_int(statement, 8, pkg_compressed); sqlite3_bind_int(statement, 9, pkg_uncompressed); sqlite3_bind_text(statement, 10, pkg_tokens[0].c_str(), -1, SQLITE_TRANSIENT); @@ -286,20 +278,15 @@ public: sqlite3_reset(statement); /* Reset for the next package */ - g_free(filename); - g_free(location); - g_free(summary); - filename = location = summary = nullptr; - g_string_assign(desc, ""); + summary.reset(); + filename.reset(); + location = ""; + desc = ""; pkg_compressed = pkg_uncompressed = 0; } - g_free(line); } sqlite3_exec(job_data->db, "END TRANSACTION", nullptr, nullptr, nullptr); - g_string_free(desc, true); - g_object_unref(data_in); - /* Parse MANIFEST.bz2 */ for (const std::string& current_priority : this->priority) { @@ -310,11 +297,6 @@ public: sqlite3_free(query); sqlite3_finalize(insert_default_statement); sqlite3_finalize(insert_statement); - - if (fin) - { - g_object_unref(fin); - } } private: @@ -335,13 +317,13 @@ private: FILE *manifest; int err, read_len; unsigned pos; - char buf[max_buf_size], *pkg_filename, *rest = nullptr, *start; + char buf[max_buf_size]; + std::optional<std::string> rest; std::filesystem::path path; - char *full_name = nullptr; - char **line, **lines; + std::vector<std::string> lines; BZFILE *manifest_bz2; - GRegex *pkg_expr = nullptr, *file_expr = nullptr; - GMatchInfo *match_info; + std::regex pkg_expr, file_expr; + std::smatch match_info; sqlite3_stmt *statement = nullptr; path = tmpl / this->name / filename; @@ -357,21 +339,13 @@ private: } /* Prepare regular expressions */ - pkg_expr = g_regex_new("^\\|\\|[[:blank:]]+Package:[[:blank:]]+.+\\/(.+)\\.(t[blxg]z$)?", - static_cast<GRegexCompileFlags> (G_REGEX_OPTIMIZE | G_REGEX_DUPNAMES), - static_cast<GRegexMatchFlags> (0), - nullptr); - file_expr = g_regex_new("^[-bcdlps][-r][-w][-xsS][-r][-w][-xsS][-r][-w]" + pkg_expr = std::regex("^\\|\\|[[:blank:]]+Package:[[:blank:]]+.+\\/(.+)\\.(t[blxg]z$)?", + std::regex::optimize); + file_expr = std::regex("^[-bcdlps][-r][-w][-xsS][-r][-w][-xsS][-r][-w]" "[-xtT][[:space:]][^[:space:]]+[[:space:]]+" "[[:digit:]]+[[:space:]][[:digit:]-]+[[:space:]]" "[[:digit:]:]+[[:space:]](?!install\\/|\\.)(.*)", - static_cast<GRegexCompileFlags> (G_REGEX_OPTIMIZE | G_REGEX_DUPNAMES), - static_cast<GRegexMatchFlags> (0), - nullptr); - if (!(file_expr) || !(pkg_expr)) - { - goto out; - } + std::regex::optimize); /* Prepare SQL statements */ if (sqlite3_prepare_v2(job_data->db, @@ -393,66 +367,50 @@ private: buf[read_len] = '\0'; /* Split the read text into lines */ - lines = g_strsplit(buf, "\n", 0); - if (rest) + boost::split(lines, buf, boost::is_any_of("\n")); + if (rest.has_value()) { /* Add to the first line rest characters from the previous read operation */ - start = lines[0]; - lines[0] = g_strconcat(rest, lines[0], nullptr); - g_free(start); - g_free(rest); + lines[0] = rest.value() + lines[0]; + rest.reset(); } if (err != BZ_STREAM_END) /* The last line can be incomplete */ { - pos = g_strv_length(lines) - 1; + pos = lines.size() - 1; rest = lines[pos]; - lines[pos] = nullptr; } - for (line = lines; *line; line++) + for (const auto& line : lines) { - if (g_regex_match(pkg_expr, *line, static_cast<GRegexMatchFlags> (0), &match_info)) + std::optional<std::string> full_name; + + if (std::regex_match(std::cbegin(line), std::cend(line), match_info, pkg_expr)) { - if (g_match_info_get_match_count(match_info) > 2) + if (match_info.size() > 2) { /* If the extension matches */ - g_free(full_name); - full_name = g_match_info_fetch(match_info, 1); + full_name = match_info.str(1); } else { - full_name = nullptr; + full_name.reset(); } } - g_match_info_free(match_info); - - match_info = nullptr; - if (full_name && g_regex_match(file_expr, *line, static_cast<GRegexMatchFlags> (0), &match_info)) + if (full_name.has_value() + && std::regex_match(std::cbegin(line), std::cend(line), match_info, file_expr)) { - pkg_filename = g_match_info_fetch(match_info, 1); - sqlite3_bind_text(statement, 1, full_name, -1, SQLITE_TRANSIENT); - sqlite3_bind_text(statement, 2, pkg_filename, -1, SQLITE_TRANSIENT); + std::string pkg_filename = match_info.str(1); + sqlite3_bind_text(statement, 1, full_name.value().c_str(), -1, SQLITE_TRANSIENT); + sqlite3_bind_text(statement, 2, pkg_filename.c_str(), -1, SQLITE_TRANSIENT); sqlite3_step(statement); sqlite3_clear_bindings(statement); sqlite3_reset(statement); - g_free(pkg_filename); } - g_match_info_free(match_info); } - g_strfreev(lines); } sqlite3_exec(job_data->db, "END TRANSACTION", nullptr, nullptr, nullptr); - g_free(full_name); BZ2_bzReadClose(&err, manifest_bz2); out: sqlite3_finalize(statement); - if (file_expr) - { - g_regex_unref(file_expr); - } - if (pkg_expr) - { - g_regex_unref(pkg_expr); - } fclose(manifest); } }; |
